主頁 > 後端開發 > 面向物件編程之繼承、多型、封裝、抽象類、介面、包

面向物件編程之繼承、多型、封裝、抽象類、介面、包

2021-04-21 11:18:26 後端開發

面向物件編程之繼承、多型、封裝、抽象類、介面、包

    • 繼承
        • 類的繼承格式
        • 為什么要繼承
        • 繼承的特點
        • 繼承的種類及關鍵字
        • 訪問權限
    • 多型
        • 向上轉型
        • 動態系結
        • 方法重寫
        • 重寫和多載的區別比較
        • 多型的優點
    • 封裝
        • 實作Java的封裝
        • 封裝的優點
    • 抽象類
        • 抽象類及其實作
        • 抽象方法
        • 抽象類使用的注意事項
    • 介面
        • 介面的宣告
        • 介面的特性
        • 抽象類和介面的區別
        • 介面與類的區別
        • 包的語法格式和匯入
        • 包的作用
    • 歡迎指正😄

繼承

繼承就是子類繼承父類的特征和行為,使得子類物件(實體)具有父類的實體域和方法,或子類從父類繼承方法,使得子類具有父類相同的行為,

類的繼承格式

在 Java 中通過 extends 關鍵字可以申明一個類是從另外一個類繼承而來的,一般形式如下:

class 父類 {
}
 
class 子類 extends 父類 {
}

為什么要繼承

從這下面兩段代碼可以看出來,代碼存在重復了,導致后果就是代碼量大且臃腫,而且維護性不高(維護性主要是后期需要修改的時候,就需要修改很多的代碼,容易出錯)

/**
 1. user:ypc;
 2. date:2021-04-20;
 3. time: 17:13;
 */
public class Dog {
    private String name;
    private int id;
    public Dog(String myName, int  myid) {
        name = myName;
        id = myid;
    }
    public void eat(){
        System.out.println(name+"正在吃");
    }
    public void sleep(){
        System.out.println(name+"正在睡");
    }
    public void introduction() {
        System.out.println("大家好!我是"         + id + "號" + name + ".");
    }
}
/**
 4. user:ypc;
 5. date:2021-04-20;
 6. time: 17:14;
 */
public class Cat {
    private String name;
    private int id;
    public Cat(String myName, int  myid) {
        name = myName;
        id = myid;
    }
    public void eat(){
        System.out.println(name+"正在吃");
    }
    public void sleep(){
        System.out.println(name+"正在睡");
    }
    public void introduction() {
        System.out.println("大家好!我是"         + id + "號" + name + ".");
    }
}

所以要從根本上解決這兩段代碼的問題,就需要繼承,將兩段代碼中相同的部分提取出來組成 一個父類:

public class Animal { 
    private String name;  
    private int id; 
    public Animal(String myName, int myid) { 
        name = myName; 
        id = myid;
    } 
    public void eat(){ 
        System.out.println(name+"正在吃"); 
    }
    public void sleep(){
        System.out.println(name+"正在睡");
    }
    public void introduction() { 
        System.out.println("大家好!我是"         + id + "號" + name + "."); 
    } 
}

這個Animal類就可以作為一個父類,然后狗類和貓類繼承這個類之后,就具有父類當中的屬性和方法,子類就不會存在重復的代碼,維護性也提高,代碼也更加簡潔,提高代碼的復用性(復用性主要是可以多次使用,不用再多次寫同樣的代碼) 繼承之后的代碼:

public class Dog extends Animal { 
    public Dog (String myName, int myid) { 
        super(myName, myid); 
    } 
}
public class Cat extends Animal { 
    public Cat (String myName, int myid) { 
        super(myName, myid); 
    } 
}

繼承的特點

🍟使用 extends 指定父類.
🍟Java 的繼承是單繼承,但是可以多重繼承,單繼承就是一個子類只能繼承一個父類,多重繼承就是,例如 B 類繼承 A 類,C 類繼承 B 類,所以按照關系就是 B 類是 C 類的父類,A 類是 B 類的父類,這是 Java 繼承區別于 C++ 繼承的一個特性
🍟子類會繼承父類的所有 public 的欄位和方法.
🍟對于父類的 private 的欄位和方法, 子類中是無法訪問的.
🍟子類的實體中, 也包含著父類的實體. 可以使用 super 關鍵字得到父類實體的參考
🍟提高了類之間的耦合性(繼承的缺點,耦合度高就會造成代碼之間的聯系越緊密,代碼獨立性越差),
🍟子類可以擁有自己的屬性和方法,即子類可以對父類進行擴展,

繼承的種類及關鍵字

🥚種類
在這里插入圖片描述
🥚關鍵字
final 關鍵字
final 關鍵字也能修飾類, 此時表示被修飾的類就不能被繼承.
父類沒有final修飾子類可以正常繼承
在這里插入圖片描述
有final關鍵字修飾父類子類不可以繼承,編譯會報錯
在這里插入圖片描述

super 關鍵字
super關鍵字:
1.super()呼叫父類的構造方法,必需放在第一行
在這里插入圖片描述
2.super.父類的成員變數,用super來呼叫父類的成員變數
在這里插入圖片描述
3.呼叫父類的成員函式 super.func()
在這里插入圖片描述

this關鍵字
指向自己的參考,
在這里插入圖片描述

extends關鍵字
在 Java 中,類的繼承是單一繼承,也就是說,一個子類只能擁有一個父類,所以 extends 只能繼承一個類,
多繼承編譯會報錯👇
在這里插入圖片描述

訪問權限

🍿private 修飾的方法和變數只可以在自己的類中訪問,子類也不可以訪問,
🍿default 就是不加private,protected,public修飾限定符修飾的方法或變數,在同一個包的同一類和不同類可以訪問default方法和變數
🍿protected相比于default,在不同包的子類可以訪問protected方法或變數,但這個類必需是它的父類,
🍿public可以在任一個類中訪問變數和方法,
🍿可以在任何一個類中使用public類
🍿不能用private和protected來修飾類
🍿訪問權限從高到低排列順序是:
public protected default private
在這里插入圖片描述

多型

向上轉型

向上轉型,JAVA中的一種呼叫方式,向上轉型是對A的物件的方法的擴充,即A的物件可訪問B從A中繼承來的和B“重寫”A的方法,
例如:

public  class Animal {
    public  String name;
    public  int age;
    public Animal(String name, int  age) {
        this.age = age;
        this.name = name;
    }
    public void eat() {
        System.out.println(this.name+"在吃東西");
    }
    public void sleep() {
        System.out.println(this.name+"在睡覺");
        }
}
class Pig extends Animal{
    public Pig(String name, int  age){
        super( name, age);
    }
    void funcPig(){
    }
   public  void eat(){
       System.out.println(this.name+"吃桃子");
    }
     void func(){
         System.out.println(super.age);
         this.eat();//呼叫自己的eat()fangfa
         super.eat();//呼叫父類的eat()方法
         this.funcPig();
     }

}

class Test{
    public static void main(String[] args) {
        /*
        正常使用
         */
        Animal animal1 = new Animal("gougou",12);
        animal1.eat();
        Pig pig  = new Pig("zhuzhu",8);
        pig.eat();
        /*
        向上轉型
         */
        Animal animal =new Pig("bajie",78);
        animal.eat();
    }


}

運行結果為:
在這里插入圖片描述

動態系結

在 Java 中, 呼叫某個類的方法, 究竟執行了哪段代碼 (是父類方法的代碼還是子類方法的代碼) , 要看究竟這個引
用指向的是父類物件還是子類物件. 這個程序是程式運行時決定的(而不是編譯期), 因此稱為 動態系結.
上面的Animal animal =new Pig(“bajie”,78);
animal.eat();就發生了動態系結
構造方法也可以發生動態系結(也叫運行時系結)
動態系結的條件:
🎊一定有向上轉型
🎊子類重寫了父類的方法,發生了方法的重寫
🎊通過父類的參考來呼叫被重寫的方法

方法重寫

子類實作父類的同名方法, 并且引數的型別和個數完全相同, 這種情況稱為 覆寫/重寫/覆寫(Override)
比如剛才的eat()方法,在Pig子類中重寫了父類Animal的eat()方法

public  class Animal {
    public  String name;
    public  int age;
    public Animal(String name, int  age) {
        this.age = age;
        this.name = name;
    }
    public void eat() {
        System.out.println(this.name+"在吃東西");
    }
    public void sleep() {
        System.out.println(this.name+"在睡覺");
        }
}
class Pig extends Animal{
    public Pig(String name, int  age){
        super( name, age);
    }
    void funcPig(){
    }
   public  void eat(){//重寫父類的eat()方法
       System.out.println(this.name+"吃桃子");
    }
     void func(){
         System.out.println(super.age);
         this.eat();//呼叫自己的eat()fangfa
         super.eat();//呼叫父類的eat()方法
         this.funcPig();
     }

}

class Test{
    public static void main(String[] args) {
        /*
        正常使用
         */
        Animal animal1 = new Animal("gougou",12);
        animal1.eat();
        Pig pig  = new Pig("zhuzhu",8);
        pig.eat();
        /*
        向上轉型
         */
        Animal animal =new Pig("bajie",78);
        animal.eat();
    }


}

針對重寫的方法, 可以使用 @Override 注解來顯式指定.
在這里插入圖片描述
如果不重寫eat()方法編譯就會報錯
在這里插入圖片描述

重寫和多載的區別比較

重寫
重寫是子類對父類的允許訪問的方法的實作程序進行重新撰寫, 回傳值和形參都不能改變,即外殼不變,核心重寫!

重寫的好處在于子類可以根據需要,定義特定于自己的行為, 也就是說子類能夠根據需要實作父類的方法,
重寫規則:

🎈引數串列與被重寫方法的引數串列必須完全相同,

🎈回傳型別與被重寫方法的回傳型別可以不相同,但是必須是父類回傳值的派生類(java5 及更早版本回傳型別要一樣,java7 及更高版本可以不同),

🎈訪問權限不能比父類中被重寫的方法的訪問權限更低,例如:如果父類的一個方法被宣告為 public,那么在子類中重寫該方法就不能宣告為 protected,

🎈父類的成員方法只能被它的子類重寫,

🎈宣告為 final 的方法不能被重寫,

🎈宣告為 static 的方法不能被重寫,但是能夠被再次宣告,

🎈子類和父類在同一個包中,那么子類可以重寫父類所有方法,除了宣告為 private 和 final 的方法,

🎈子類和父類不在同一個包中,那么子類只能夠重寫父類的宣告為 public 和 protected 的非 final 方法,

🎈重寫的方法能夠拋出任何非強制例外,無論被重寫的方法是否拋出例外,但是,重寫的方法不能拋出新的強制性例外,或者比被重寫方法宣告的更廣泛的強制性例外,反之則可以,

🎈構造方法不能被重寫,

🎈如果不能繼承一個類,則不能重寫該類的方法
多載
多載(overloading) 是在一個類里面,方法名字相同,而引數不同,回傳型別可以相同也可以不同,
每個多載的方法(或者建構式)都必須有一個獨一無二的引數型別串列,
多載規則:

🎄被多載的方法必須改變引數串列(引數個數或型別不一樣);
🎄被多載的方法可以改變回傳型別;
🎄被多載的方法可以改變訪問修飾符;
🎄被多載的方法可以宣告新的或更廣的檢查例外;
🎄方法能夠在同一個類中或者在一個子類中被多載,
🎄無法以回傳值型別作為多載函式的區分標準,
在這里插入圖片描述

多型的優點

🎁 消除型別之間的耦合關系
🎁可替換性
🎁可擴充性
🎁介面性
🎁靈活性
🎁簡化性
🎁多型存在的三個必要條件
1.繼承
2.重寫
3.父類參考指向子類物件:Parent p = new Child();
多型的實作方式
🚗方式一:重寫:
參見上文
🚗方式二:介面
java中的介面類似于生活中的介面,就是一些方法特征的集合,但沒有方法的實作,
參見下文
🚗方式三:抽象類和抽象方法
參見下文

封裝

在面向物件程式設計方法中,封裝(英語:Encapsulation)是指一種將抽象性函式介面的實作細節部分包裝、隱藏起來的方法,
封裝可以被認為是一個保護屏障,防止該類的代碼和資料被外部類定義的代碼隨機訪問,
要訪問該類的代碼和資料,必須通過嚴格的介面控制,
封裝最主要的功能在于我們能修改自己的實作代碼,而不用修改那些呼叫我們代碼的程式片段,
適當的封裝可以讓程式碼更容易理解與維護,也加強了程式碼的安全性,

實作Java的封裝

  1. 修改屬性的可見性來限制對屬性的訪問(一般限制為private)如:
/**
 * user:ypc;
 * date:2021-04-20;
 * time: 19:15;
 */
public class Person {
    private String name;
    private int age;
}

這段代碼中,將 name 和 age 屬性設定為私有的,只能本類才能訪問.如此就對資訊進行了隱藏,
2. 對每個值屬性提供對外的公共方法訪問,也就是創建一對賦取值方法,用于對私有屬性的訪問如:get\set方法(idea快捷鍵alt+Ins插入)

/**
 * user:ypc;
 * date:2021-04-20;
 * time: 19:15;
 */
public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

在這里插入圖片描述
3.實體化

/**
 * user:ypc;
 * date:2021-04-20;
 * time: 19:15;
 */
public class Person {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
class TestDemo{
    public static void main(String[] args) {
        Person person = new Person();
        person.setAge(20);
        person.setName("jack");
        System.out.println(person.getName());
        System.out.println(person.getAge());

    }
}

結果
在這里插入圖片描述

封裝的優點

🎨良好的封裝能夠減少耦合,

🎨類內部的結構可以自由修改,

🎨可以對成員變數進行更精確的控制,

🎨隱藏資訊,實作細節

抽象類

抽象類及其實作

在面向物件的概念中,所有的物件都是通過類來描繪的,但是反過來,并不是所有的類都是用來描繪物件的,如果一個類中沒有包含足夠的資訊來描繪一個具體的物件,這樣的類就是抽象類,
由于抽象類不能實體化物件,所以抽象類必須被繼承,才能被使用,
父類包含了子類集合的常見的方法,但是由于父類本身是抽象的,所以不能使用這些方法,
例如:Person就是一個抽象類

public abstract class Person {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void Work(){}
}
class Teacher extends Person{
    public void Work(){
        System.out.println(this.getName()+"的作業是教書");
    }
}
class Student extends  Person{
    public void Work(){
        System.out.println(this.getName()+"的作業學習");
    }
}
class TestDemo{
    public static void main(String[] args) {
     //   Person person = new Person();不能實體化否則編譯就會報錯
        person.setAge(20);
        person.setName("jack");
        System.out.println(person.getName());
        System.out.println(person.getAge());

    }
}

在這里插入圖片描述

抽象方法

如果你想設計這樣一個類,該類包含一個特別的成員方法,該方法的具體實作由它的子類確定,那么你可以在父類中宣告該方法為抽象方法,
Abstract 關鍵字同樣可以用來宣告抽象方法,抽象方法只包含一個方法名,而沒有方法體,
抽象方法沒有定義,方法名后面直接跟一個分號,而不是花括號,
如:Pereon類中的Work()方法
在這里插入圖片描述
抽象方法必需被重寫否則就會報錯

/**
 * user:ypc;
 * date:2021-04-20;
 * time: 19:15;
 */
public abstract class Person {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
   // public void Work(){}
    public abstract  void Work();
}
class Teacher extends Person{//抽象方法必需被重寫否則就會報錯
    public void Work(){
        System.out.println(this.getName()+"的作業是教書");
    }
}
class Student extends  Person{
    public void Work(){
        System.out.println(this.getName()+"的作業是學習");
    }
}
class TestDemo{
    public static void main(String[] args) {
        Person person = new Student();
        person.setName("Steven");
        person.Work();
//        Person person = new Person();
//        person.setAge(20);
//        person.setName("jack");
//        System.out.println(person.getName());
//        System.out.println(person.getAge());

    }
}

在這里插入圖片描述

抽象類使用的注意事項

👧如果一個類包含抽象方法,那么該類必須是抽象類,
任何子類必須重寫父類的抽象方法,或者宣告自身為抽象類,
👧繼承抽象方法的子類必須重寫該方法,否則,該子類也必須宣告為抽象類,最終,必須有子類實作該抽象方法,否則,從最初的父類到最終的子類都不能用來實體化物件,
👧抽象類可以發生向上轉型,可以被繼承,可以動態系結
👧抽象類不能被實體化
👧抽象類被繼承時方法一定要重寫
👧抽象類存在的意義就是為了被繼承
👧抽象方法不能是private
👧抽象類可以有非抽象方法

介面

介面是抽象類的更進一步. 抽象類中還可以包含非抽象方法, 和欄位. 而介面中包含的方法都是抽象方法, 欄位只能包含
靜態常量.
介面(英文:Interface),在JAVA編程語言中是一個抽象型別,是抽象方法的集合,介面通常以interface來宣告,一個類通過繼承介面的方式,從而來繼承介面的抽象方法,

介面并不是類,撰寫介面的方式和類很相似,但是它們屬于不同的概念,類描述物件的屬性和方法,介面則包含類要實作的方法,

除非實作介面的類是抽象類,否則該類要定義介面中的所有方法,

介面無法被實體化,但是可以被實作,一個實作介面的類,必須實作介面內所描述的所有方法,否則就必須宣告為抽象類,另外,在 Java 中,介面型別可用來宣告一個變數,他們可以成為一個空指標,或是被系結在一個以此介面實作的物件

介面的宣告

[可見度] interface 介面名稱 [extends 其他的介面名] {
// 宣告變數
// 抽象方法
}
例如:IShape就是一個介面

interface IShape {
    void draw();
}
class Rect implements  IShape{
    public void draw(){
        System.out.println("?");
    }
}
class Cycle implements IShape {
    public void draw() {
        System.out.println("○");
    }
}
 class TestDemo2 {
    public static void main(String[] args) {
        IShape shape = new Rect();
        shape.draw();
    }
}

介面的特性

🎦介面是隱式抽象的,當宣告一個介面的時候,不必使用abstract關鍵字,
🎦介面中每一個方法也是隱式抽象的,宣告時同樣不需要abstract關鍵字,
🎦介面中的方法都是公有的,
也就是說interface IShape{}中的方法默認都是從public abstrat的,并且不能有具體實作
變數默認都是public abstrat final的
🎦介面可以向上轉型,可以發生運行時系結即動態系結
🎦介面中的方法可以具體實作但必須是這樣的:default void function(){…}
🎦一個類可以實作多個介面
🎦介面的實作就是為了滿足繼承
🎦介面可以拓展
🎦一個類可以實作一個介面也可以繼承一個類
如下:
在這里插入圖片描述

class A{

}
interface IShape {
    void draw();
}
/*
🎦一個類可以實作多個介面
🎦介面的實作就是為了滿足繼承
🎦介面可以拓展
🎦一個類可以實作一個介面也可以繼承一個類
 */
interface IShape2 extends IShape {
    void draw();
}
class Rect extends A implements  IShape,IShape2{
    public void draw(){
        System.out.println("?");
    }
}
class Cycle implements IShape {
    public void draw() {
        System.out.println("○");
    }
}
 class TestDemo2 {
    public static void main(String[] args) {
        IShape shape = new Rect();
        shape.draw();
    }
}

抽象類和介面的區別

🎅抽象類中的方法可以有方法體,就是能實作方法的具體功能,但是介面中的方法不行,
🎅 抽象類中的成員變數可以是各種型別的,而介面中的成員變數只能是 public static final 型別的,
🎅介面中不能含有靜態代碼塊以及靜態方法(用 static 修飾的方法),而抽象類是可以有靜態代碼塊和靜態方法,
🎅 一個類只能繼承一個抽象類,而一個類卻可以實作多個介面,

介面與類的區別

🤶介面不能用于實體化物件,
🤶介面沒有構造方法,
🤶介面中所有的方法必須是抽象方法,
🤶介面不能包含成員變數,除了 static 和 final 變數,
🤶介面不是被類繼承了,而是要被類實作,
🤶介面支持多繼承

為了更好地組織類,Java 提供了包機制,用于區別類名的命名空間,

包的語法格式和匯入

包的語法格式
package pkg1[.pkg2[.pkg3…]];
包的匯入
import package1[.package2…].(classname|*);
例如:Demo6匯入了B包中的Demo5類并在主函式中實列化了Demo5類,使用了Demo5類的func函式
同時也繼承了A介面(不能實作A介面(不能使用implements介面),只能繼承)
在這里插入圖片描述

在這里插入圖片描述
包B中的Demo5類的代碼

package B;

/**
 * user:ypc;
 * date:2021-04-20;
 * time: 20:46;
 */
interface A{
    public void test();
}
public class Demo5 {
    public void func(){
        System.out.println("匯入了B包中的Demo5類的func()方法");
    }
}

包外類Demo6的代碼

import B.Demo5;
/**
 * user:ypc;
 * date:2021-04-20;
 * time: 20:46;
 */
class B extends A {
    public void test(){
        System.out.println("繼承了B包中的A介面的test方法");
    }
}
public class Demo6 {
    public static void main(String[] args) {
        B b = new B();
        b.test();
        Demo5 demo5 = new Demo5();
        demo5.func();

    }

}

包的作用

📆把功能相似或相關的類或介面組織在同一個包中,方便類的查找和使用,

📆如同檔案夾一樣,包也采用了樹形目錄的存盤方式,同一個包中的類名字是不同的,不同的包中的類的名字是可以相同的,當同時呼叫兩個不同包中相同類名的類時,應該加上包名加以區別,因此,包可以避免名字沖突,

📆包也限定了訪問權限,擁有包訪問權限的類才能訪問某個包中的類,

Java 使用包(package)這種機制是為了防止命名沖突,訪問控制,提供搜索和定位類(class)、介面、列舉(enumerations)和注釋(annotation)等,

歡迎指正😄

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/278461.html

標籤:java

上一篇:mybatis練習-獲取擁有“普通用戶”角色的所有用戶資訊,要求查詢結果除了包含用戶自身資訊,還包括角色名和角色創建時間。

下一篇:seleinum中解決需要定位到iframe中嵌套iframe的問題,Message: no such element: Unable to locate element

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more