JavaStudy—B站韩顺平(类变量+类方法+代码块+单例设计模式+Final关键字+抽象类)

  • List item

JavaStudy—B站hsp

一、java面向对象回顾

1.IDEA使用

1.快捷键

在这里插入图片描述

2.包的本质和命名规范

在这里插入图片描述
在这里插入图片描述

2.访问修饰符

3.1基本介绍

java 提供四种访问控制修饰符号,用于控制方法和属性(成员变量)的访问权限(范围):

\1) 公开级别:用 public 修饰,对外公开

\2) 受保护级别:用 protected 修饰,对子类和同一个包中的类公开

\3) 默认级别:没有修饰符号,向同一个包的类公开.

\4) 私有级别:用 private 修饰,只有类本身可以访问,不对外公开.

3.2种访问修饰符的访问范围

在这里插入图片描述

3.面向对象编程三大特征

3.1基本介绍

面向对象编程有三大特征:封装、继承和多态。

3.2封装介绍

封装就是把抽象出的数据**[属性]**和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法],才能对数据进行操作。

3.2.1封装的理解和好处
//(1)隐藏实现细节:方法(连接数据库)<--调用(传入参数..)
//(2)可以对数据进行验证,保证安全合理
Person {name,age}
Person p = new Person();
p.name = "jack";
p.age = 12;
3.2.2封装的实现步骤 (三步)

在这里插入图片描述

3.3面向对象编程-继承
3.3.1.为什么需要继承

1.提高代码的复用性

2.当两个类具有相同的特征(属性)和行为(方法)时,可以相同的部分抽取出来放到一个类中作为父类,其他两个类继承这个父类。

3.3.2.继承基本介绍和示意图

继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可。画出继承的示意图
在这里插入图片描述

3.3.3.继承的基本语法

在这里插入图片描述

3.3.4继承给编程带来的便利

  1. 代码的复用性提高了

  2. 代码的扩展性和维护性提高了

3.3.5继承的深入讨论/细节问题

  1. 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问;

  2. 子类必须调用父类的构造器, 完成父类的初始化 ;

  3. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无 参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译 不会通过(怎么理解。) [举例说明]

  4. 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)

  5. super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)

  6. super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

  7. java 所有类都是 Object 类的子类, Object 是所有类的基类.

  8. 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)

  9. 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制。

思考:如何让 A 类继承 B 类和 C 类? 【A 继承 B, B 继承 C】

  1. 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系
3.3.4子类创建的内存布局

在这里插入图片描述

3.3.5 super 给编程带来的便利/细节

在这里插入图片描述

3.3.6 super 和 this 的比较

在这里插入图片描述

3.3.7方法重写/覆盖(override)

1.基本介绍

在这里插入图片描述

2.注意事项和使用细节

在这里插入图片描述

3.对方法的重写和重载做一个比较

在这里插入图片描述

3.4多[多种]态[状态]基本介绍

方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。

3.4.1多态的具体体现
  1. 方法的多态 PloyMethod.java

重写和重载就体现多态 [案例说明:]

public class PloyMethod { 
    public static void main(String[] args) { 
        //方法重载体现多态 
        A a = new A(); //这里我们传入不同的参数,就会调用不同 sum 方法,就体现多态 
        System.out.println(a.sum(10, 20));
        System.out.println(a.sum(10, 20, 30)); 
        //方法重写体现多态 
        B b = new B();
        a.say(); 
        b.say();  
    }
}
class B { //父类 
    public void say() { 
        System.out.println("B say() 方法被调用...");
    } 
}
class A extends B {//子类 
    public int sum(int n1, int n2){
        //和下面 sum 构成重载 
        return n1 + n2; 
    }
    public int sum(int n1, int n2, int n3){ 
        return n1 + n2 + n3; 
    }
    public void say() { 
        System.out.println("A say() 方法被调用...");
    } 
}
  1. 对象的多态 (核心,困难,重点)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yxEH8kmv-1646381623979)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220227155454905.png)]

3.4.2多态注意事项和细节讨论

多态的前提是:两个对象(类)存在继承关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MHiD89Yj-1646381623980)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220227155724671.png)]

3.4.3java 的动态绑定机制(非常非常重要.)

Java 重要特性: 动态绑定机制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zVLQc7dH-1646381623981)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220227160106081.png)]

二、 面向对象高级部分

(一)类变量(静态变量)

无论jdk版本如何,记住一点:static静态变量被对象共享

不管static变量在哪里,共识(1)static变量是同一个类所有对象共享(2)static在类加载的时候就生成了。

1.什么是类变量

​ 类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个类的对象去访问它时,取到的都是相同的值,同样的任何一个该类的对象去修改它时,修改的也是同一个变量。

2.如何定义类变量

**定义语法:**访问修饰符 static 数据类型 变量名(推荐)

​ static 访问修饰符 数据类型 变量名

3.如何访问类变量

​ 类名.类变量名(推荐)

​ 对象名.类变量名【静态变量的访问修饰符的访问权限和范围 和 普通属性时一样的。】

在这里插入图片描述

在这里插入图片描述

代码示例:

public class VisitStatic {
    public static void main(String[] args) {
        //类名.类变量名
        //说明:类变量是随着类的加载而创建,所以即使没有创建对象实例也可以访问
        System.out.println(A.name);
        //通过对象名.类变量名
        A a = new A();
        System.out.println(a.name);
    }
}
class A{
    //类变量
    //类变量的访问,必须遵守 相关的访问权限.
    public static String name = "覃波";

(二)类方法/静态方法

1.基本介绍

/**
 * 学生收费
 */
public class StaticMethod {
    public static void main(String[] args) {
        //创建两个对象交学费
        Student student1 = new Student("小明");
        student1.payFee(2000);

        Student student2 = new Student("小红");
        student2.payFee(3000);

        //Student.payFee(500);  通过类名.类方法  也可以访问  也会该改变类变量fee的值
        //输出当前的总学费
        Student.showFee();

        //如果我们希望不创建实例,也可以调用某个方法(即当做工具来使用)
        //这时,把方法做成静态方法时非常合适
        System.out.println("9开平方的结果是:" + Math.sqrt(9));
        //调用MyTools中的类方法使用和上面Math中的aqrt一样的情况
        System.out.println(MyTools.calSum(10, 15));
    }
}

//开发自己的工具类.可以将方法做成静态的,方便调用
class MyTools{
    //求出两个数之和
    public static double calSum(double n1,double n2){
        return n1+n2;
    }
}

class Student{
    //普通成员
    private String name;
    //定义一个静态变量,来积累学生的学费
    public static double fee;

    public Student(String name) {
        this.name = name;
    }
    //说明
    //1.当方法使用了static修饰后,该方法就是静态方法
    //2.静态方法就可以访问静态属性
    public static void payFee(double fee){
        Student.fee += fee;
    }

    public static void showFee(){
        System.out.println("总学费:" + Student.fee);
    }
}
2.类方法注意事项

在这里插入图片描述
在这里插入图片描述

public class StaticMethodDetail {
    public static void main(String[] args) {

    }
}
class D{
    private int n1 = 100;
    private static int n2 = 200;
    public void say(){  //非静态方法/普通方法

    }
    //静态方法/类方法
    public static void hi(){
        //类方法中不允许使用和对象有关的关键字
        //比如 this 和 super。普通方法(成员方法)可以
//        System.out.println(this.n1);
    }
    //类方法(静态方法)中 只能访问 静态变量 或静态方法
    // 口诀:静态方法只能访问静态成员.
    public static void hello(){
        System.out.println(n2);
        System.out.println(D.n2);
        //System.out.println(D.n1);//不能使用
        hi();//静态方法ok
        // say();错误
    }
    //普通成员方法,既可以访问 非静态成员,也可以访问静态成员
    //小结: 非静态方法可以访问 静态成员和非静态成员
    public void ok() {
        //非静态成员 
        System.out.println(n1); 
        say(); //静态成员 
        System.out.println(n2); 
        hello(); }
}
2.1练习题

1

在这里插入图片描述

2

class Person { //StaticExercise02.java 2min 时间 

private int id;

private static int total = 0; 

public static int getTotalPerson() { 

//id++;//错误, 注销 

return total; 

}

public Person() {//构造器 

total++; //total = 1 

id = total;//id = 1 

} 

}

public class TestPerson { 

public static void main(String[] args) { 

System.out.println("Number of total is " +Person.getTotalPerson()); //0 

Person p1 = new Person(); 

System.out.println( "Number of total is "+ Person.getTotalPerson()); //1 

} 

} 

3

class Person { //StaticExercise03.java 2min 看
    private int id; 
    private static int total = 0; 
    public static void setTotalPerson(int total){
        // this.total = total;//错误,因为在 static 方法中,不可以使用 this 关键字 
        Person.total = total; 
    }
    public Person() {
        //构造器 
        total++; id = total; }}
public class TestPerson { 
    public static void main(String[] args) {
        Person.setTotalPerson(3);
        new Person(); 
        //最后 total 的值就是 4 
    } }小结:记住两句话 (1) 静态方法,只能访问静态成员 (2) 非静态方法,可以访问所有的成员 (3) 在编写代码时,仍然要遵守访问权限规则

小结:记住两句话 (1) 静态方法,只能访问静态成员 (2) 非静态方法,可以访问所有的成员 (3) 在编写代码时,仍然要遵守访问权限规则

(三)main方法

1.深入理解main方法

解释main方法的形式:public static void main(String[] args){}

  1. main方法是虚拟机在调用
  2. java虚拟机需要调用main()方法,所以该方法的访问权限必须是public
  3. java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static
  4. 该方法接收String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数,案例演示,接受参数。
  5. java 执行的程序 参数1 参数2 参数3

在这里插入图片描述

特别提示:

  1. 在 main()方法中,我们可以直接调用 main 方法所在类的静态方法或静态属性。

  2. 但是,不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员

(四)代码块

1.基本介绍

​ 代码块又称为初始化块,属于类中的成员【即 是类的一部分】,类似于方法,将逻辑语句封装在方法体中,通过{}包围起来。

​ 但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不通过对象或类显示调用,而是类加载时,或创建对象时隐式调用。

2.基本语法

[修饰符]{

​ 代码

}

说明注意:

  1. 修饰符 可选,要写的话只能写static
  2. 代码块分为两类,使用static 修饰的叫静态代码块,没有static修饰的,叫普通代码块/非静态代码块
  3. 逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环、判断等)
  4. **;**可以写上,也可以省略。
3.代码块的好处和案例演示
  1. 相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作。

  2. 场景:如果多个构造器中有重复的语句,可以抽取到初始化块中,提高代码的复用性

  3. 案例

    谨记:代码块调用的顺序优先于构造器…

public class CodeBlock01 {
    public static void main(String[] args) {
        Movie movie = new Movie("你哈");
        System.out.println("==============================");
        Movie movie1 = new Movie("你哈",200,"王仁");
    }

}
class Movie{
    private String name;
    private double price;
    private  String director;
    //3 个构造器-》重载
    //1.下面三个构造器都有相同的语句
    //2.这样看起来代码比较冗余
    //3.这时我们可以把相同的语句,放入到一个代码块中,即可
    //4.这样当我们不管调用哪个构造器,创建对象,都会先调用代码块的内容
    //5.代码块调用的顺序优先于构造器..
    {
        System.out.println("电影显示器打开");
        System.out.println("电影广告");
        System.out.println("电影正式开始");
    }
    public Movie(String name) {
//        System.out.println("电影显示器打开");
//        System.out.println("电影广告");
//        System.out.println("电影正式开始");
        System.out.println("Movie(String name) 被调用...");
        this.name = name;
    }

    public Movie(String name, double price) {
        /*System.out.println("电影显示器打开");
       System.out.println("电影广告");
       System.out.println("电影正式开始");*/
        this.name = name;
        this.price = price;
    }

    public Movie(String name, double price, String director) {
//        System.out.println("电影显示器打开");
//        System.out.println("电影广告");
//        System.out.println("电影正式开始");
        System.out.println("Movie(String name, double price, String director) 被调用...");
        this.name = name;
        this.price = price;
        this.director = director;
    }

}
4.代码块使用注意事项和细节
  1. static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次。如果是普通代码块,每创建一个对象就执行。
  2. 类什么时候被加载【重要】

①创建对象实例时

②创建子类对象实例时,父类也会被加载

③使用类的静态成员时(静态属性,静态方法)

  1. 普通的代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会调用一次。 如果只是使用类的静态成员时,普通代码块并不会执行。

    小结:1.static代码块是类加载时,执行,只会执行一次
    2.普通代码块是在创建对象时调用的,创建一次,调用一次
    3.类加载的3种情况,需要记住。

    案例演示:

public class CodeBlockDetail01 {
    public static void main(String[] args) {
        //类被加载的情况举例
        // 1. 创建对象实例时(new)
        //AA aa = new AA();
        //2. 创建子类对象实例,父类也会被加载, 而且,父类先被加载,子类后被加载
        //AA aa = new AA();
        //3. 使用类的静态成员时(静态属性,静态方法)
        //System.out.println(Cat.n1);
        //DD dd = new DD();
        //DD dd1 = new DD();
        //普通的代码块,在创建对象实例时,会被隐式的调用。
        // 被创建一次,就会调用一次。
        // 如果只是使用类的静态成员时,普通代码块并不会执行
        System.out.println(DD.n1);//8888, 静态模块块一定会执行

    }
}
class DD {
    public static int n1 = 8888;//静态属性
    // 静态代码块
    static {
     System.out.println("DD 的静态代码 1 被执行...");
     }
    //普通代码块, 在 new 对象时,被调用,而且是每创建一个对象,就调用一次
    //可以这样简单的,理解 普通代码块是构造器的补充
    {
        System.out.println("DD 的普通代码块...");
    }
}

class Animal {
    //静态代码块
   static {
    System.out.println("Animal 的静态代码 1 被执行...");
     }
}

class Cat extends Animal{
    public static int n1 = 999;//静态属性
    // 静态代码块
    static {
        System.out.println("Cat 的静态代码 1 被执行...");
     }
}

class BB{
    static {
        System.out.println("BB 的静态代码 1 被执行...");
    }
}

class AA extends BB{
    static {
        System.out.println("AA 的静态代码 1 被执行...");
    }
}
  1. 创建一个对象时,在一个类调用顺序是:(重点,难点):

    ①调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果多个静态代码块和多个静态变量初始化,则按他们的顺序调用)(再次提示,静态代码块只随类加载一次)

    ②调用普通代码块和普通属性初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果多个普通代码块和多个普通变量初始化,则按他们的顺序调用)(再次提示,普通代码块只随创建对象实例加载)

    ③调用构造方法

代码演示:

public class CodeBlockDetail02 {

    public static void main(String[] args) {
        A a = new A();//1.getN1被调用。。2.A 静态代码块
        B b = new B();//3.getN2被调用。。4.B 静态代码块
        System.out.println("===========");
        new A();//静态代码块只执行一次
        new B();//getN2被调用。.    B 静态代码块     B 的构造方法
    }
}
class A{
    //静态属性的初始化
    private static int n1 = getN1();

    static {//静态代码块
        System.out.println("A 静态代码块");
    }

    public static int getN1(){
        System.out.println("getN1被调用。。");
        return 100;
    }
}

class B{

    public B(){
        System.out.println("B 的构造方法");
    }
    //普通属性初始化
    private int n2 = getN2();
    {
        System.out.println("B 静态代码块");
    }
    public int getN2(){
        System.out.println("getN2被调用。。");
        return 101;
    }
}
  1. 构造器 的最前面其实隐含了super()和调用普通代码块,新写一个类演示【截图+说明],静态相关的代码块,属性初始化,在类加载时,就执行完毕因此是优先于构造器和普通代码块执行的。 CodeBlockDetail03.java

在这里插入图片描述

代码演示:

public class CodeBlockDetail03 {
    public static void main(String[] args) {
        new BBB();// 1.AAA 的普通代码块被调用 2.AAA的构造器被调用 3.BBB普通代码块 4.BBB的构造器被调用
    }
}

class AAA{
    public AAA(){
        System.out.println("AAA的构造器被调用");
    }
    {
        System.out.println("AAA 的普通代码块被调用");
    }
}

class BBB extends AAA{

    {
        System.out.println("BBB普通代码块");
    }
    public BBB(){
        //1.super();
        //2.调用本类的普通代码块
        System.out.println("BBB的构造器被调用");
    }
}

  1. 我们看一下创建一个子类对象时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:
    父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
    子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
    父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
    父类的构造方法
    子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
    子类的构造方法 //面试题
    AAAAA extends BBBBB类演示[10Min]55 CodeBlockDetail04.java

  2. 静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员。学习比较麻烦,工作轻松

代码演示:

public class CodeBlockDetail04 { 
    public static void main(String[] args) { 
        //老师说明
        //(1) 进行类的加载
        //1.1 先加载 父类 A02 1.2 再加载 B02 
        //(2) 创建对象
        //2.1 从子类的构造器开始 
        //new B02();
        //对象 new C02(); 
    } 
}
class A02{ //父类 
    private static int n1 = getVal01(); 
    static {
        System.out.println("A02 的一个静态代码块..");//(2)
    }
    { 
        System.out.println("A02 的第一个普通代码块..");//(5) 
    }
        public int n3 = getVal02();//普通属性的初始化 
    public static int getVal01() { System.out.println("getVal01");//(1) 
       return 10; 
    }
    public int getVal02(){
        System.out.println("getVal02");//(6)
        return 10; 
    }
    public A02() {//构造器 
        //隐藏 
        //super() 
        //普通代码和普通属性的初始化...... 
        System.out.println("A02 的构造器");//(7) 
    } }
class C02 { 
    private int n1 = 100; 
    private static int n2 = 200; 
    private void m1() {
    }
    private static void m2() {
    }
    static {
        //静态代码块,只能调用静态成员
        //System.out.println(n1);错误 
        System.out.println(n2);//ok 
        //m1();
        //错误 m2(); 
    }
    { //普通代码块,可以使用任意成员 
        System.out.println(n1); 
        System.out.println(n2);//ok 
        m1(); 
        m2(); 
    } }
class B02 extends A02 { 
    private static int n3 = getVal03(); 
    static {
        System.out.println("B02 的一个静态代码块..");//(4) 
    }
    public int n5 = getVal04(); 
    { 
        System.out.println("B02 的第一个普通代码块..");//(9)
         }
    public static int getVal03() { 
        System.out.println("getVal03");//(3)
        return 10; 
    }
    public int getVal04() { System.out.println("getVal04");//(8) 
        return 10; 
    }
    //一定要慢慢的去品.. 
    public B02() {//构造器 
        //隐藏了 
        //super() 
        //普通代码块和普通属性的初始化... 
        System.out.println("B02 的构造器");//(10) 
        // TODO Auto-generated constructor stub } }

(五)单例设计模式

1.什么是设计模式

在这里插入图片描述

2.什么是单例模式

单例(单个的实例)

  1. 所谓类的单例设计模式,就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类提供一个能取得其对象实例的方法。
  2. 单例模式有两种:1.饿汉式 2.懒汉式
2.1单例模式应用实例

在这里插入图片描述

2.2饿汉式vs懒汉式

在这里插入图片描述

2.3代码演示:

饿汉式:

/**
 * 演示饿汉式-单例模式
 */
public class SingleTon01 {
    public static void main(String[] args) {
        //    GirlFriend xh = new GirlFriend("小红");
//    GirlFriend xb = new GirlFriend("小白");
        //直接通过方法获取对象
        GirlFriend instance = GirlFriend.getInstance();
        System.out.println(instance);
        GirlFriend instance2 = GirlFriend.getInstance();
        System.out.println(instance2);//只会出现一个对象

        System.out.println(instance == instance2);
    }
}
//有一个类, GirlFriend
// 只能有一个女朋友
class GirlFriend{
    private String name;
    //为了能够在静态方法中,返回 gf 对象,需要将其修饰为 static
    private static GirlFriend girlFriend = new GirlFriend("小甜甜");
    //如何保障我们只能创建一个 GirlFriend 对象
    //步骤
    //1.将构造器私有化
    //2.在类的内部直接创建
    private GirlFriend(String name) {
        this.name = name;
    }
    public static GirlFriend getInstance(){
        return girlFriend;
    }

    @Override
    public String toString() {
        return "GirlFriend{" +
                "name='" + name + '\'' +
                '}';
    }
}

懒汉式:

/**
 * 演示懒汉式 -单例模式
 */
public class SingleTon02 {
    public static void main(String[] args) {
        Cat cat = Cat.getInstance();
        System.out.println(cat);//Cat{name='猫猫'}
        //再次调用getInstance()
        Cat cat1 = Cat.getInstance();
        System.out.println(cat1);//Cat{name='猫猫'}

        System.out.println(cat ==cat1); //ture

    }
}
//希望在程序运行中,只能创建一个Cat对象
//使用单例模式
class Cat {
    private String name;
    private static Cat cat;
    //步骤
    //1.构造器私有化
    //2.定义一个atatic静态属性对象
    //3.提供一個 public 的 static 方法,可以返回一個 Cat 對象
    //4.
    public Cat(String name) {
        this.name = name;
    }
    public static Cat getInstance(){
        if (cat == null){
            cat = new Cat("猫猫");
        }
        return cat;
    }

    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                '}';
    }
}

(六)Final关键字

1.基本介绍

在这里插入图片描述

代码演示:

/**
 * Final关键字
 */
public class Final01 {
    public static void main(String[] args) {
        E e = new E();
        //e.TAX_RATE =0.09; final修饰属性 常量无法更改
    }
}

//如果我们要求 A 类不能被其他类继承
// 可以使用 final 修饰 A 类
final class A{

}
//class B extends A{}

class C{
    //如果我们要求 hi 不能被子类重写
    // 可以使用 final 修饰 hi 方法
    public final void hi(){}
}
class D extends C{
    //无法重写hi
//    @Override
//    public void hi(){}
}

//当不希望类的的某个属性的值被修改,可以用 final 修饰
class E{
    public  final double TAX_RATE = 0.08;//常量
}

//当不希望某个局部变量被修改,可以使用 final 修饰
class F{
    public void cry() {
        //这时,NUM 也称为 局部常量
        final double NUM = 0.01;
        //NUM = 0.9;
        System.out.println("NUM=" + NUM); }
}
2.Final使用注意事项和细节讨论
  1. final修饰得属性又叫常量,一般用XX_XX来命名

  2. final修饰的属性在定义时,必须赋初值,并且以后不能在修改,复制可以在如下位置之一

    • 定义时:如public final double TAX_RATE = 0.08;//常量
    • 在构造器中
    • 在代码块中
  3. 如果final修饰得属性是静态的则初始化的位置只能是

    定义时 ②在静态代码块中

    不能在构造器中(静态随类加载,构造器随对象加载)

  4. f**inal类不能被继承,**但是可以实例化对象

  5. 如果类不是final类,但是含有final方法;则该类可以被继承,但是final方法不能被重写

  6. final不能修饰**构造方法(**即构造器)

  7. final和static往往搭配使用,效率会更高,不会导致类的加载,底层编译器做了优化处理。

  8. 包装类(Integer,Double,Float,Boolean等等都是final类),String也是final类

final应用实例:

/**
 * 请编写一个程序,能够计算圆形的面积。
 * 要求圆周率为3.14.赋值的位置3个方式都写一下
 */
public class FinalExercise01 {
    public static void main(String[] args) {
        Round round = new Round(10);
        System.out.println(round.calArea());
    }
}
class Round{
    private double r;
    //定义时赋值
    public final static double PI = 3.14;
    public final  double PI1;
    public final  double PI2;
    //代码块赋值
    {
        PI1 = 3.14;
    }
    //构造器赋值
    public Round( double r){
        this.r = r;
        PI2 = 3.14;
    }

    public double calArea(){
            return PI*r*r;
    }
    public double calArea1(){
        return PI1*r*r;
    }
}

(七)抽象类

在这里插入图片描述

1.抽象类入门和介绍

在这里插入图片描述

2.抽象类使用的注意事项和细节讨论
  1. 抽象类不能被实例化;

在这里插入图片描述

  1. 抽象类不一定包含abstract方法,也就是说,抽象类可以没有抽象abstract方
    在这里插入图片描述

  2. 一旦包含了abstract方法,则这个类必须声明为abstract类

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U76tFDzk-1646381623995)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20220303171335557.png)]

  3. abstract只能修饰类和方法,不能修饰属性和其他的。

在这里插入图片描述

  1. 抽象类可以有任意成员【抽象类的本质还是类】,比如非抽象方法,构造器、静态属性等等

在这里插入图片描述

  1. 抽象方法不能有主体,即不能实现
  2. 如果一个类继承了一个抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract类

[外链图片转在这里插入图片描述
在这里插入图片描述

  1. 抽象方法不能使用private、final、static修饰符来修饰,因为这些关键字都是和重写相违背了
  • private 私有的,无法重写
  • final 最终的,本身就是为了静止修改原来的值
  • static 静态的 与重写无关
3.抽象类练习

4. 抽象类最佳实践-模板设计模式

在这里插入图片描述

4.1最佳实践

在这里插入图片描述

4.2自我总结:

AAA和BBB都继承于Temple这个抽象(abstract)类,Temple有一个job抽象方法。这里AAA需要实现job()方法计算1+…100000的循环时间,然后BBB也需要实现job()方法,也是计算时间,只不过他们的数字不同。他们都需要计算时间,而且计算时间的代码是一样的,这时候我们就把相同代码提取出来,在抽象类Temple写成一个公开的方法calculateTime()用于计算时间,将不相同的代码留在job()方法中,在父类calculateTime()中去调用job()方法给出范围进行时间计算。

当我们有两个类的代码相似时,我们可以同时继承一个抽象类,将相同代码合并成方法写在父类中,不同的代码留在子类同名方法中,当我们new子类对象时就可以直接调用父类的方法使用。

public class TestTemple {
    public static void main(String[] args) {
        AAA aaa = new AAA();
        aaa.job();
//        BBB bbb = new BBB();
//        bbb.job();
    }
}
abstract public class Temple {//抽象类
    public abstract void job();//抽象方法

    public void calculateTime(){ //实现方法 调用job方法
        //得到开始的时间
        long start = System.currentTimeMillis();
        job();//动态绑定机制
        //得到结束的时间
        long end = System.currentTimeMillis();
        System.out.println("" + (end - start));
    }
}
public class AAA extends Temple {
    //计算任务
    //从1+2+。。。10000;
   @Override
    public void job(){

        long sum = 0;
        for (long i = 1; i <=1000000; i++) {
            sum +=i;
        }

    }
}
public class BBB extends Temple{
    //计算任务
    //从1+2+。。。10000;
    @Override
    public void job(){
        long sum = 0;
        for (long i = 1; i <=1000000; i++) {
            sum *=i;
        }
    }
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别来无恙blwy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值