java自学 -- OOP进阶2

我发现还有其他哥们和我一起在跟着韩老师学习,然后笔记也大部分重复,导致原创没通过,就先改成转载的好了,那哥们真是比我勤快多了,1个月前就学到这了

代码块

是什么

​ 代码化块又称为初始化块,属于类中的成员[即是类的一部分],类似于方法,将逻辑语句封装在方法体中,通过 {} 包围起来。
​ 但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类时,或创建对象时隐式调用。

基本语法

[修饰符]{
    代码
};   //可以没有; //我觉得还是有比较好,这样比较容易和其他的区分开来

说明注意:
1) 修饰符可选, 要写的话只能写static
2) 代码块分为两类, 使用static修饰的叫静态代码块, 没有static修饰的, 叫普通代码块/非静态代码块。
3)逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环、判断等)
4);号可以写上,也可以省略。

什么情况用

	-  相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作
	-  场景:如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性

细节(重点)

  • static代码块也叫静态代码块, 作用就是对类进行初始化, 而且它随着类的加载而执行,并且只会执行一次。如果是普通代码块,每创建一个对象,就执行一次。
  • 类什么时候被加载**[重要背!]**
    • 创建对象实例时(new)
    • 创建子类对象实例,父类也会被加载
    • 使用类的静态成员时(静态属性,静态方法)
  • 普通的代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会调用一次。
    如果只是使用类的静态成员时,普通代码块并不会执行。

小结:

​ 1.static代码块是类加载时, 执行, 且只会执行一次

​ 2.普通代码块是在创建对象时调用的,创建一次,调用一次

​ 3.类加载的3种情况,需要记住.

public class CodeBlock01 {
    public static void main(String[] args) {
//        Person person = new Person();
//        Person person1 = new Person();
//        Person person2 = new Person();静态代码块只调用一次
        
        System.out.println(Person.n1);//普通的代码块没调用,静态的调用了
    }
}

class Person{
    static{
        System.out.println("静态代码块调用");
    };
    {
        System.out.println("普通代码块调用");
    };
    static int n1 = 100;
}

  • 创建一个对象时,在一个类调用顺序:(重点,难点)

    • 调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用)
    • 调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按定义顺序调用)
    • 调用构造方法
  • 构造器的最前面其实隐含了super() 和调用普通代码块, 静态相关的代码块,属性初始化,在类加载时,就执行完毕,因此是优先于构造器和普通代码块执行的

class A{
	public A() {    //构造器
	//这里有隐藏的执行要求
	//(1) super() ; //这个知识点, 在前面讲解继承的时候, 老师说
	//(2)调用普通代码块的
	System.out.print In("ok")}    
}        
  • 静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员。

代码块执行顺序

​ 创建一个子类对象时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:

​ ①父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
​ ②子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
​ ③父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
​ ④父类的构造方法
​ ⑤子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
​ ⑥子类的构造方法


单例设计模式

​ 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己再思考和摸索。

​ 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。

​ 单例模式有两种方式:1)饿汉式2)懒汉式

//1)饿汉式
//构造器私有化=》防止直接new
//类的内部创建对象
//向外暴露一个静态的公共方法
public class Single01 {
    public  static void main(String[] args){
        Cat cat = Cat.getInstance();
    }
}

class Cat{
    private String name;
    private static Cat cat = new Cat("哈哈");

    private Cat(String name) {
        System.out.println("有参构造器被调用..");
        this.name = name;
    }

    public static Cat getInstance(){
        return cat;
    }
}
//2)懒汉式懒汉式
//构造器私有化=》防止直接new
//类的内部创建对象
//向外暴露一个静态的公共方法
public class Single02 {
    public static void main(String[] args){
        Dog dog = Dog.getInstance();
        Dog dog1 = Dog.getInstance();
        System.out.println(dog == dog1);
    }
}


class Dog{
    private String name;
    private static Dog dog;
    private Dog(String name) {
        System.out.println("有参构造器被调用..");
        this.name = name;
    }
    public static Dog getInstance(){
        if(dog == null){
            dog = new Dog("阿巴阿巴");
        }
        return dog;
    }
    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                '}';
    }
}

饿汉式和懒汉式 区别

  • 二者最主要的区别在于创建对象的时机不同:饿汉式是在类加载就创建了对象实例,而懒汉式是在使用时才创建
  • 饿汉式不存在线程安全问题,懒汉式存在线程安全问题
  • 饿汉式存在浪费资源的可能。因为如果程序员一个对象实例都没有使用,那么饿汉式创建的对象就浪费了,懒汉式是使用时才创建,就不存在这个问题

final

​ final可以修饰类、属性、方法和局部变量。

final class  Test{ }  //类
final int TAX_RATE = 111;//属性
public final void hah(){ }  //方法

在某些情况下, 程序员可能有以下需求, 就会使用到final:

  • 当不希望类被继承时, 可以用final修饰
  • 当不希望父类的某个方法被子类覆盖/重写(override) 时, 可以用final关键字修饰
  • 当不希望类的的某个属性的值被修改, 可以用final修饰
  • 当不希望某个局部变量被修改, 可以使用final修饰

细节

- final修饰的属性又叫常量, 一般用XX_XX_XX来命名	
  • final修饰的属性在定义时, 必须赋初值, 并且以后不能再修改, 赋值可以在如下位置之一【选择一个位置赋初值即可】:
//定义时
public final double TAX_RATE=0.08

//在构造器中
class  Test{
    final double TAX_RATE;   
    public Test() {
        TAX_RATE = 0.8;
    }
} 
    
//在代码块中
class  Test{
    final double TAX_RATE;
    {
        TAX_RATE = 0.8;
    }
}
  • 如果final修饰的属性是静态的, 则初始化的位置只能是
    • 定义时
      • 在静态代码块不能在构造器中赋值
final class  Test{
    static final double TAX_RATE;
    static{
        TAX_RATE = 0.8;
    }
} 			//可行
----------------------------------------------------------
final class  Test{
    static final double TAX_RATE;
    {
        TAX_RATE = 0.8;  //报错
    }
}    // XXXXXXXXXXXXX   ---不行
- final类不能继承, 但是可以实例化对象
- 如果类不是final类, 但是含有final方法, 则该方法虽然不能重写, 但是可以被继承
- 一般来说, 如果一个类已经是final类了, 就没有必要再将方法修饰成final方法
- final不能修饰构造方法(即构造器)
- final和static往往搭配使用,效率更高,不会导致类加载,底层编译器做了优化处理
public class FinalTest {
    public static void main(String[] args){
        System.out.println(Test.aa);//10 类没有加载
    }
}

class Test{
    static final int aa = 10;
    static{
        System.out.println("Test类被加载了");
    }
}
- 包装类(Integer, Double, Float, Boolean等都是final) , String也是final类

抽象类

​ 当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类。

//用abstract关键字来修饰一个类时, 这个类就叫抽象类
访问修饰符 abstract class 类名{
    
    //用abstract关键字来修饰一个方法时, 这个方法就是抽象方法
    访问修饰符 abstract void 方法名();  //没有方法体 {}
    
    //有返回值的方法
    public abstract double hh(double hh);       
}

//抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类)

细节

  • 抽象类不能被实例化
  • 抽象类不一定要包含abstract方法。也就是说, 抽象类可以没有abstract方法
  • 一旦类包含了abstract方法, 则这个类必须声明为abstract
  • abstract只能修饰类和方法, 不能修饰属性和其它的
  • 抽象类可以有任意成员【抽象类本质还是类】,比如:非抽象方法、构造器、静态属性等等
  • 抽象方法不能有主体(方法体),即不能实现
  • 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract类
  • 抽象方法不能使用 private、final 和 static 来修饰,因为这些关键字都是和重写相违背的

模版设计模式

​ 抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。

  • 当功能内部一部分实现是确定,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。
  • 编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其子类实现,就是一种模板模式.
//实例 - 模版设计模式
public abstract class Template {  //抽象类父类
    public abstract void job(); //抽象方法
    public void calculateTime(){  //普通方法
        long start = System.currentTimeMillis();
        //统一的部分写进去
        //System.currentTimeMillis() 统计1970年至今的毫秒数
        job(); //不确定的交由子类重写方法
        long end = System.currentTimeMillis();
        System.out.println("任务工作时间" + (end-start));
    }
}
// AA子类
public class AA extends Template{  // 继承抽象父类
    @Override
    public void job() {  //重写父类抽象方法
        long sum = 0;
        for (long i = 1; i < 1000000; i++) {
            sum += i;
        }
    }
}
// BB子类
public class BB extends Template{  // 继承抽象父类
    @Override
    public void job() {  //重写父类抽象方法
        long sum = 0;
        for (long i = 1; i < 1000000; i++) {
            sum *= i;
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值