java基础——final接口内部类

java基础


笔记的都是需要背诵的零散知识点,以顺序的方式组织



1.单例模式

  • 静态方法和属性的经典实用
  • 设计模式的理解:设计模式是在大量的实践中总结和理论化之后优选的代码结构,编程风格,以及解决问题的思考方式。设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己再思考和摸索
  • 单例模式:
    单例模式:就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法
    单例模式两种方法:(1)饿汉式(2)懒汉式

2.饿汉式VS懒汉式

  • 二者最主要的区别在于创建对象的实际不同:
    饿汉式是在类加载就创建了对象实例
    懒汉式是在使用时才创建
  • 饿汉式不存在线程安全问题,懒汉式存在线程安全问题
  • 饿汉式存在浪费资源的可能。因为如果程序员一个对象实例都没有使用,那么饿汉式创建的对象浪费了,懒汉式是在使用时才创建没救不存在这个问题
  • 在我们javaSE标准中,java.lang.Runtime就是经典的单例模式

3.final关键字

  • 常量,不希望被继承覆盖重写修改——final
  • final 可以修饰、类、属性、方法、局部变量
  • 程序员可能使用的场景需求:
    (1)不希望类被继承时——final
    (2)不希望父类的某个方法被子类覆盖/重写(override)时——final
      案例【访问修饰符 final 返回类型 方法名】
    (3)不希望类的某个属性的值被修改——final
      案例【public final double TAX_RATE=0.08】
    (4)不希望类的某个局部变量被修改——final
      案例【final double TAX_RATE=0.08】

4.final小细节

(1)final修饰的属性又叫常量,XX_XX_XX命名
(2)final修饰的属性在定义时,必须赋初值,常量不能修改。
(3)常量赋值可以加在如下位置之一:
 ①定义时:public final double TAX_RATE=0.08
 ②在构造器中
 ③在代码块中
(4)类final了不能被继承,但是可以实例化对象
(5)如果类不是final类,但是含有final方法,虽然方法不能重写,但是可以被继承
(6)类已经是final类了,没必要再将方法修饰成final方法
(7)final和static往往搭配使用,效率更高,不会导致类加载。底层编译做了优化处理
(8)包装类(Integer,Double,Float,Boolean 等都是final)String也是final类

5.抽象类

  • 当父类的一些方法不确定时,但是需要声明,可以用abstract关键字修饰,就是抽象方法
  • 因为实现了没什么意义
  • 抽象类:
    (1)用abstract关键字来修饰一个类时,这个类就叫抽象类。
     案例【访问修饰符 abstract 类名{ }】
    (2)用abstract关键字来修饰一个方法时,这个方法就是抽象方法
     案例【访问修饰符abstract返回类型方法名(参数列表);//没有方法体】
    (3)抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类()
    (4)抽象类,是考官比较爱问的知识点,在框架和设计模式使用较多
  • 抽象类细节:
    (1)抽象类不能被实例化
    (2)抽象类不一定要包含abstract方法
    (3)一旦包含了abstract方法,则这个类必须声明为abstract类
    (4)abstract只能修饰类和方法,不能修饰属性和其他的
    (5)抽象类可以有任意成员,比如非抽象方法,构造器,静态属性等等
    (6)抽象类本质还是类
    (7)抽象方法不能有主体abstract void aaa();加花括号错
    (8)如果一个类继承了抽象类,他必须实现抽象类的所有抽象方法,除非也声明为抽象类
    (9)抽象方法不能使用private、final、static类修饰,因为这些是和重写相违背的

6.抽象类——模板设计模式

  • 理解:抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类再抽象类得基础上进行扩展,改造,但子类总体上会保留抽象类的行为方式
  • 模板设计能解决的问题
    (1)当功能内部一部分实现是确定的,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现
    (2)编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其子类实现,就是一种模板模式

6.接口

  • 语法:
    interface 接口名{
    //属性
    //抽象方法
    }
    class 类名 implements 接口{
    //自己属性;
    //自己方法;
    //必须实现接口的抽象方法

}

  • 接口理解:就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候再根据具体情况把这些方法写出来
  • 接口是更加抽象的抽象类
  • 抽象类里的方法可以有方法体,接口里的所有方法都没有方法体
  • 接口不能被实例化
  • 接口中所有的方法是public方法,接口中抽象方法,可以不用abstract修饰:
    void aaa();
    实际上是: abstract void aa();
  • 一个普通类实现接口,就必须将接口的所有方法的都实现
  • 抽象类实现接口,可以不用实现接口的方法
  • 一个类同时可以实现多个接口
  • 接口中的属性,只能是final的,而且是public static final 修饰符
    案例【int a=1;实际上 public static final int a =1;】
  • 接口中属性的访问形式:接口名.属性名
  • 接口中不能继承其他的类。但是可以继承多个别的接口
  • 接口的修饰符 只能是public 和默认,这点和类的修饰符是一样的

7.接口继承比较

  • 继承的主要价值在于:解决代码的复用和可维护性
  • 接口的价值主要在于:设计,设计好各种规范(方法),让其他类去实现这些方法更加灵活
  • 接口在一定程度上实现代码解耦

8.接口的多态性

  • 多态参数,可以接收多种对象的参数
  • 多态数组,
  • 接口存在多态传递现象

9.内部类

  • 一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。
  • 类的五大成员是哪些?
    [属性、方法、构造器、代码块、内部类]
  • 内部类最大的特点:就是可以直接访问私有属性,并且可以体现类与类之间的包含关系。(看底层源码时,有大量的内部类)
  • 语法:
    在这里插入图片描述
  • 内部类的分类:
    局部就是在成员的局部位置
    在这里插入图片描述

10.局部内部类

  • 位置:局部内部类是定义在外部类的局部位置,比如方法中
  • 局部类有类名
  • 可以直接访问外部类的所有成员,包含私有的
  • 作用域:仅仅在定义他的方法或者代码块中
  • 局部内部类---->访问---->外部类的成员【访问方式:直接访问】
  • 外部类---->访问---->局部内部类的成员【访问方式:创建对象,在访问,必须在作用域内】
  • 外部其他类-----不能访问----->局部内部类(因为局部内部类地位是一个局部变量)
  • 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问

11.匿名内部类

  • 位置:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名,且还是一个对象
  • 语法:

在这里插入图片描述

  • 理解:匿名内部类的语法比较奇特,是类又是对象,两者的特征都有
  • 可以直接访问外部类的所有成员,包含私有的
  • 不能添加访问修饰符,地位是局部变量
  • 作用域:仅仅在定义他的方法或代码块中
  • 匿名内部类----->访问----->外部类成员【访问方式:直接访问】
  • 外部其他类---->不能访问---->匿名内部类(局部变量)
  • 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问

12.局部内部类VS匿名内部类区别

局部内部类和匿名内部类行为和能力差不多。局部内部类的名字在方法外是不可见的。匿名内部类用过一次就不在使用,而使用局部内部类的理由是,需要不止一个该内部类对象。

13.局部内部类匿名内部类只能final的局部变量?

首先,我们看一个局部内部类的例子:

class OutClass {
	private int age = 12;
 
	public void outPrint(final int x) {
		class InClass {
			public void InPrint() {
				System.out.println(x);
				System.out.println(age);
			}
		}
		new InClass().InPrint();
	}
}

这里有一个外部类OuterClass和一个内部类InClass,内部类访问了外部类的一个方法中的一个局部变量x,在这里,x必须是final的,否则会报错:
Cannot refer to a non-final variable x inside an inner class defined in a different method


追究其根本原因就是作用域中变量的生命周期导致的;

 先需要知道的一点是:内部类和外部类是处于同一个级别的,内部类不会因为定义在方法中就会随着方法的执行完毕就被销毁.

 这里就会产生问题:当外部类的方法结束时,局部变量就会被销毁了,但是内部类对象可能还存在(只有没有人再引用它时,才会死亡)。这里就出现了一个矛盾:内部类对象访问了一个不存在的变量。为了解决这个问题,就将局部变量复制了一份作为内部类的成员变量,这样当局部变量死亡后,内部类仍可以访问它,实际访问的是局部变量的”copy”。这样就好像延长了局部变量的生命周期。我们可以通过反编译生成的.class文件来实验:

 在命令行窗口中先执行命令” javac OutClass.java”进行编译,会得到两个文件: OutClass$1InClass.class、OutClass.class:
在这里插入图片描述
  javap是 Java class文件分解器,可以反编译,也可以查看java编译器生成的字节码。

 这里我们可以再执行命令”javap -privateOutClass$1InClass”进行反编译,”-private”表示显示所有类和成员,执行后会得到如下结果:
在这里插入图片描述
 可见方法中的局部变量实际上确实会复制为内部类的成员变量使用。

 问题又出现了:将局部变量复制为内部类的成员变量时,必须保证这两个变量是一样的,也就是如果我们在内部类中修改了成员变量,方法中的局部变量也得跟着改变,怎么解决问题呢?

 就将局部变量设置为final,对它初始化后,我就不让你再去修改这个变量,就保证了内部类的成员变量和方法的局部变量的一致性。这实际上也是一种妥协折中。

 若变量是final时:

 若是基本类型,其值是不能改变的,就保证了copy与原始的局部变量的值是一样的;

 若是引用类型,其引用是不能改变的,保证了copy与原始的变量引用的是同一个对象。

 这就使得局部变量与内部类内建立的拷贝保持一致。维持了数据的一致性。
 java8中匿名/局部内部类访问局部变量时,局部变量已经可以不用加final了,但其实这个局部变量还是final的,只不过不用显式的加上而已,实际上是底层帮我们加上了。

14.成员内部类

  • 位置说明:成员内部类是定义在外部类的成员位置,并且没有static修饰

  • 可以一直间接访问外部类的所有成员,包含私有的

  • 可以添加任意访问修饰符(public protected 默认 private)(成员)

  • 作用域:和外部类的其他成员一样,为整个类体

  • 成员内部类---->访问---->外部类成员(比如属性)【访问方式:直接访问】

  • 外部类---->访问---->成员内部类【访问方式:创建对象,在访问】

  • 外部其他类---->访问---->成员内部类

  • 如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问

  • 外部类访问方式:
     第一种:编写一个方法,然后方法返回对象【间接】
     第二种:类名称 对象名 =new 类名称();
    外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();

在这里插入图片描述

15.静态内部类

  • 位置说明:静态内部类是定义在外部类的位置上,并且有static修饰
  • 访问都类似
  • 可以直接访问外部类的所有今天成员,包含私有的,但不能直接访问非静态成员
  • 可以添加任意访问修饰符(public、protected、默认、private)
  • 作用域:同其他成员,为整个类
  • 静态内部类---->访问---->外部类(比如静态属性)【访问方式:直接访问所有静态成员】
  • 外部类----访问------->静态内部类【访问方式:创建对象,再访问】
  • 外部其他类----->访问------>静态内部类
  • 如果外部类和静态内部类的成员重名时,静态内部类访问的时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)去访问

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值