自学Java的知识盲点(面向对象编程)

2023-11-19

目录

1.类和对象

1.1对象(属性+行为)

1.1.1属性/成员变量

1.2类和对象的内存分配机制

1.3构造方法

1.3.1this关键字

1.4访问修饰符

2.封装

2.1定义:

3.继承(ctrl+h可以看继承关系)

3.1基本介绍:(本质:先加载父类在加载子类)

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

3.2.1super关键字

3.2.2this和super的区别

4.方法的重写

5.多态

5.1基本介绍

5.1.1对于多态的理解

5.2多态的具体体现

1.方法的多态

2.对象的多态

3.多态成员变量:编译运行看左边

5.3案例说明

5.4向上(向下)转型

5.5细节推理

5.6 instanceOf

5.7Java的动态绑定机制

6.类变量和类方法

6.1基本介绍

6.1.1什么是类变量

6.1.2如何定义类变量

6.1.3static共识

6.1.4类变量的理解

6.2类变量使用注意事项

6.3类方法

6.3.1基本介绍

6.3.2类方法的调用

6.3.3类方法的使用

6.3.4类方法的注意事项

7.main方法的理解

7.1解释main方法的形式

8.代码块

8.1基本介绍

8.2基本语法

8.3好处

8.4小细节

9.final关键字

9.1基本介绍

9.2注意事项

10.抽象类

10.1基本介绍

10.2细节

11.接口

11.1基本介绍

11.2注意事项

11.3接口和继承的区别

11.4接口和抽象的区别

12内部类

12.1基本介绍

12.2基本语法

12.3内部类的分类

12.4局部内部类的使用

12.5匿名内部类

12.5.1基本介绍

12.5.2基本语法

12.5.3实例说明

12.6注意事项

13.内部类

13.1成员使用

13.2静态内部类使用

14.枚举

14.1枚举的引入

14.2自定义枚举

14.3 enum关键字实现枚举

14.3.1 enum 关键字实现枚举注意事项

14.4 enum 常 用方法说明

14.5注意事项

14.6lamda

15.注解

15.1注解的理解

15.2三个基本的 Annotation:

15.3元注解

15.3.1@Retention

15.3.2@Targe

15.3.3@Documented

15.3.4@Inherited 注解


1.类和对象

1.1对象(属性+行为)

  1. 类是抽象的,概念的,代表一类事物,比如人类,猫类...即它是数据类型。

  2. 对象是具体的,实际的,代表一个具体事物,即是实例。

  3. 类是对象的模板,对象是类的一个个体,对应一个实例。

代码在内存里面new 了一个对象之后:

名字和颜色是String类型故此会在堆里面有一个地址,指向方法区中的常量池中的数据(按照引用的方式),int 是基本数据类型会直接存放在堆里面

会将类的信息加载到方法区然后就会开始分配空间,根据属性不一样分配不同的空间,如果是字符串就会分配一个地址指向常量池,基本数据类型就放在堆里面,然后最后将这个地址在返回给Cat

Cat只是对象名,真正的对象是堆和方法区里面的数据

1.1.1属性/成员变量

1.从概念和叫法上面看:成员变量=属性=field(字段)(即成员变量是用来表示属性的)

2.属性是类的一个组成部分,一般是基本类型也可能是引用类型(数组,对象)。

3.属性的定义类型可以为任意类型,包含基本类型或者引用类型。

4.属性如果赋值,有默认值,规则和数组一样

1.2类和对象的内存分配机制

Person  p1=new Person();
p1.age=10;
p1.name="小明";
Person p2=p1;
System.out.println(p2.age);

解释说明:

  1. 首先会在方法区加载Person信息(属性信息和方法信息,只会加载一次),

  2. new会在堆里面开辟空间(就会有一个地址),

  3. 初始化属性,

  4. 把地址赋值给p1,p1就指向对象,

  5. 直到执行到p1.age=10;p1.name="小明";这个就会在方法区存储小明,返回一个地址给name,在堆里面直接存80,

  6. 最后将p1的地址给p2,同时p2也会指向这个堆里面的空间,

  7. 并且p1和p2调用的属性都是一样的

1.3构造方法

  1. 构造方法必须和类名相同

  2. 构造方法没有返回值类型

  3. 构造方法是用来初始化数据的,不是创建对象

  4. 一个类可以定义多个不同的构造器,即构造器重载

  5. 在创建对象时,系统自动的调用该类的构造方法

  6. 如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器)

  7. 一旦定义了自己的构造器,默认的构造器就覆盖了,就不能在使用默认的无参构造器,除非显示的定义一下

1.3.1this关键字

Java虚拟机会给每个对象分配this,代表当前对象

譬如:小狗有很多属性,但是当小狗说:我的年龄,的时候就会直接想到小狗的年龄,这个this就是我的的意思

this.age=age;//就是当前对象的属性,就是小狗这个对象的年龄属性

这里的this指向它自己

那个对象调用,this就代表哪个对象

1.4访问修饰符

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

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

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

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

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

2.封装

2.1定义:

1、封装的概念: 将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来对隐藏的信息进行操作和访问。 2、好处: (1)只能通过规定的方法访问数据 (2)隐藏类的实例细节,方便修改和实现。 3、封装的实现步骤 (1)修改属性的可见性设为(private) (2)创建getter/setter方法(用于属性的读写)(通过这两种方法对数据进行获取和设定,对象通过调用这两种发方法实现对数据的读写) (3)在getter/setter方法中加入属性控制语句(对属性值的合法性进行判断)

(4)后续条件在setxxx里面添加

//余额(必须>20)
public void setBalance(double balance) { 
    if (balance > 20) { 
        this.balance = balance; 
    } else {
        System.out.println("余额(必须>20) 默认为 0"); } 
}

3.继承(ctrl+h可以看继承关系)

3.1基本介绍:(本质:先加载父类在加载子类)

继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中

抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来

声明继承父类即可。画出继承的示意图

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

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

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

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

理解:子类会自动去调用父类的无参构造器,若是父类没有无参构造器,必须要写super();[访问本类成员父类变量的值]

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

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

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

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

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

package frame.基础;
public class Text01 {
    public static void main(String[] args) {
        C a = new C();
    }
static class A{
        public  A(){
            System.out.println("这个是A的无参构造器");
        }
}
static class B extends A{
    public  B(){
        System.out.println("这个是B的无参构造器");
    }
}
    static class C extends B{
        public  C(){
            System.out.println("这个是C的无参构造器");
        }
    }
}

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

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

\10) 不能滥用继承,子类和父类之间必须满足 is-a[。。。是一个。。。] 的逻辑关系

3.3继承的本质分析

先加载Object类,接着加载GrandPa,GrandPa加载完成后加载Father,最后加载Son类,首先是加载这个Son但是因为这个Son的父类还有父类,所以先从Object开始加载,然后在堆中给Son开辟一个地址空间,并且先将GrandPa类的属性放入堆里面,之后会在开一个空间将Father的属性存入其中,最后会在开一个空间将Son的属性存入其中,

堆的数据分配好了以后,堆地址就会分配给主方法里面的Son对象引用

3.2.1super关键字

  1. super 代表父类的引用,用于访问父类的属性、方法、构造

  2. 访问父类的属性,但不能访问父类的private属性。

    super.属性名

  3. 访问父类的方法,不能访问弗雷德private方法

    super.方法名(参数列表);

  4. 访问父类的构造器

    super(参数列表);只能出现在第一行(this),只能出现一次

    this访问本类的属性和成员方法

    super访问父类的属性和成员方法

  5. super在每个构造函数都有,只是有的没有写出来

    3.2.2this和super的区别

4.方法的重写

方法重写也叫方法覆盖,注意事项:

  1. 子类的方法的形参列表,方法名称,要和父类方法的形参列表,方法名称完全一样,

  2. 子类方法的返回类型要和父类方法的返回类型一样,或者是父类返回类型的子类(比如父类的返回类型是Object,子类方法的返回类型是String)

  3. 子类方法不能缩小父类方法的访问权限:public > protected > 默认 > private

5.多态

5.1基本介绍

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

5.1.1对于多态的理解

通过继承将父类的方法在子类重写,然后进行向上转型

A a=new B();
a.bbb();//执行B里面的方法

就可以定义形参的时候为父类的类型,但是调用的时候就会传进去参数为子类的数据,譬如:

车行: 凯迪拉克,迈凯伦,毒药,等等

用来描述车的性能:

可以定义一个方法,

public void Performance(Cat cat,Speed speed){
        System.out.println("车名"+cat.getCat+"速度"+speed.getSpeed);
}

车的种类就可以调用这个方法,因为是Cat类型(父类),所以编译类型也是父类,但是因为运行类型是子类故此传入的值是子类的,这样就可以减少代码的复用性,不用在进行杂七杂八的方法调用和重写了。

注意:

以为编译类型是父类,所以无法调用子类特有的成员,因为在编译阶段能编译那些成员是由编译类型决定的(父类里面有的方法才可以调用[重写]),但是有向下转型就可以

5.2多态的具体体现

1.方法的多态

重写和重载就体现多态

2.对象的多态

  1. 一个对象的编译类型和运行类型可以不一致(运行类型就是运行的函数)

Fu f1=new Zi();
System.out.println(f1.show());//f1的门面类型是Fu,但实际类型是Zi,所以调用的是重写后的方法。

  1. 编译类型在定义对象时,就确定了,不能改变

  2. 运行类型是可以改变的

  3. 编译类型看定义是 = 号的左边,运行类型看 = 的右边

3.多态成员变量:编译运行看左边

Fu f=new Zi();
System.out.println(f.num);//f是Fu中的值,只能取到父中的值

5.3案例说明

public class Animal { 
    String name = "动物"; 
    int age = 10; 
    public void sleep(){ 
        System.out.println("睡"); 
    }
    public void run(){
        System.out.println("跑");
        }
    public void eat(){ 
        System.out.println("吃"); 
    }
    public void show(){ 
        System.out.println("hello,你好"); 
    } 
}
​
public class Cat extends Animal { 
    public void eat(){//方法重写
        System.out.println("猫吃鱼"); 
    }
    public void catchMouse(){//Cat 特有方法 
        System.out.println("猫抓老鼠");
    } }
​
​
public class Dog extends Animal {
    //Dog 是 Animal 的子类 
}
​
​
public class PolyDetail { 
    public static void main(String[] args) {
        //向上转型: 父类的引用指向了子类的对象 
        //语法:父类类型引用名 = new 子类类型();
        Animal animal = new Cat(); 
        Object obj = new Cat();
        //可以吗? 可以 Object 也是 Cat 的父类 
        //向上转型调用方法的规则如下: 
        //(1)可以调用父类中的所有成员(需遵守访问权限) 
        //(2)但是不能调用子类的特有的成员 
        //(#)因为在编译阶段,能调用哪些成员,是由编译类型来决定的 
        //animal.catchMouse();错误 
        //(4)最终运行效果看子类(运行类型)的具体实现, 即调用方法时,按照从子类(运行类型)开始查找方法
        //,然后调用,规则我前面我们讲的方法调用规则一致。 
        animal.eat(); //猫吃鱼.. a
        nimal.run();//跑
        animal.show();//hello,你好 
        animal.sleep(); //睡 
        //老师希望,可以调用 Cat 的 catchMouse 方法 
        //多态的向下转型 
        //(1)语法:子类类型 引用名 =(子类类型)父类引用; 
        //问一个问题? cat 的编译类型 Cat,运行类型是 
        Cat Cat cat = (Cat) animal; 
        cat.catchMouse();
        //猫抓老鼠
        //(2)要求父类的引用必须指向的是当前目标类型的对象
        Dog dog = (Dog) animal; //可以吗?
        System.out.println("ok~~"); 
    }
}

5.4向上(向下)转型

5.4.1向上转型

  1. 本质:父类的引用指向了子类的对象

  2. 语法:父类类型 引用名=new 子类类型();

  3. 特点:编译类型看左边,运行类型看右边

    可以调用父类中的所以成员(需要遵守访问权限)

    不能调用子类的特有成员

    最终运行效果看子类的具体实现

5.4.2向下转型

  1. 语法:子类类型 引用名=(子类类型)父类引用;

  2. 只能强转父类的引用,不能强转父类的对象

  3. 要求父类的引用必须指向的是当前目标类型的对象

这个引用先要指向父类,只能才能向下转型指向子类

   ```java

Object obj = new Integer;//向上转型 String str = (String)onj;//错误,指向Integer的父类引用,转成String Integer Str1=(Integer) obj;//正确的向下转型 ```

4.当向下转型后,可以调用子类类型中的所有的成员

5.5细节推理

public class PolyDetail02 { 

	public static void main(String[] args) { 

		//属性没有重写之说!属性的值看编译类型 

	Base base = new Sub();//向上转型 

	System.out.println(base.count);// ? 看编译类型 10 

	Sub sub = new Sub(); 

	System.out.println(sub.count);//? 20 

		} 

}

class Base { //父类 

	int count = 10;//属性 

}

class Sub extends Base {//子类 

	int count = 20;//属性 

}

5.6 instanceOf

比较操作符,用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型

5.7Java的动态绑定机制

  1. 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型(运行类型在堆里面,有一个地址)绑定

  2. 当调用对象属性时,没有动态绑定机制,哪里声明,那里使用

public class DynamicBinding { 
​
public static void main(String[] args) { 
​
//a 的编译类型 A, 运行类型 B 
​
A a = new B();//向上转型 
​
System.out.println(a.sum());//?40 -> 30 
​
System.out.println(a.sum1());//?30-> 20 
​
} 
​
}
​
class A {//父类 
​
public int i = 10; 
​
//动态绑定机制: 
​
public int sum() {//父类 sum() 
​
return getI() + 10;//20 + 10 
​
第 332页**韩顺平循序渐进学** **Java** **零基础**
​
第 333页 
​
}
​
public int sum1() {//父类 sum1() 
​
return i + 10;//10 + 10 
​
}
​
public int getI() {//父类 getI 
​
return i; 
​
} 
​
}
​
class B extends A {//子类 
​
public int i = 20; 
​
// 
​
public int sum() { 
​
// 
​
return i + 20; 
​
// 
​
}
​
public int getI() {//子类 getI() 
​
return i; 
​
} 
​
// 
​
public int sum1() { 
​
// 
​
return i + 10; 
​
// 
​
} 
​
}

6.类变量和类方法

6.1基本介绍

6.1.1什么是类变量

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

6.1.2如何定义类变量

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

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

6.1.3static共识

  1. static变量时同一个类所有对象共享

  2. static类变量,在类加载的时候就生成了

6.1.4类变量的理解

当我们需要一个变量在这个类的所有对象里面都去进行访问的时候,就可以去使用类变量,因为类变量可以被多个对象去访问并且操作的,而且操作数据都会同步到所有的对象上。所有的对象都是对于类变量进行一个统一的操作,即一个对象将类变量(count)+1,其他的对象都会收到这个+1操作的反馈

6.2类变量使用注意事项

  1. 什么时候需要用类变量

    当我们需要让某个类的所以对象都共享一个变量时,就可以考虑使用类变量(静态变量):比如:定义学生类,统计所以学生共交多少钱。

  2. 类变量与实例变量的区别

    类变量是该类的所以对象共享的,而实例变量是每个对象共享的。

  3. 加上static称为类变量或静态变量,否则称为实例变量/普通变量/非静态变量

  4. 类变量可以通过类名.类变量名或者对象名.类变量名来访问,但Java设计者推荐我们使用类名.类变量名方式来访问

  5. 实例变量不能通过类名.类变量名方式访问

  6. 类变量是在累计在时就初始化了,也就是说,即便你没有常见对象,只要类加载了,就可以使用类变量了。

  7. 类变量的生命周期是随类的记载开始,随着类的消亡而销毁

6.3类方法

6.3.1基本介绍

类方法也叫静态方法。

形式如下:

访问修饰符 static 数据返回类型 方法名(){}[推荐]

static 访问修饰符 数据返回类型 方法名(){}

6.3.2类方法的调用

类名.类方法名或者对象名.类方法名

6.3.3类方法的使用

当方法中不涉及到任何和对象相关的成员,则可以将方法设计成静态方法,提高开发效率。

比如∶工具类中的方法 utils


Math类、Arrays类、Collections集合类看下源码∶

>小结
在程序员实际开发,往往会将一些通用的方法,设计成静态方法,这样我们不需要创建对象就可以使用了,比如打印一维数组,冒泡排序,完成某个计算任务 等…

6.3.4类方法的注意事项

2)类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区:

类方法中无this的参数

普通方法中隐含着this的参数

2)类方法可以通过类名调用,也可以通过对象名调用。

3)普通方法和对象有关,需要通过对象名调用,比如对象名.方法名(参数),不能通过类名调用。

4)类方法中不允许使用和对象有关的关键字,比如this和super。普通方法可以。

5)类方法中只能访问静态变量或静态方法。

6)普通成员方法,既可以访问非静态方法也可以访问静态方法

小结

静态方法,只能访问静态的成员,非静态的方法,可以访问静态成员和非静态成员

7.main方法的理解

7.1解释main方法的形式

  1. main方法是虚拟机调用

  2. Java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public(因为不在类里面调用)

  3. Java虚拟机在执行main()方法时不必创建对象,所以该方法必须时static

  4. 该方法接受String类型的数组参数,该数组中保存执行Java命令时传递给所运行的类的参数

  5. Java执行的程序 参数1 参数2 参数3(在执行这个程序的时候在这个程序的后面参进去的)

可以这样添加:

public class Text01 {
    public static void main(String[] args) {
        for (String a:args
             ) {
            System.out.println(a);
        }
​
    }
}
​

结果:

帅红 海绵hong

7.2理解main方法语法

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

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

态成员,

8.代码块

8.1基本介绍

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

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

8.2基本语法

[修饰符]{

代码

}

注意:

  1. 修饰符可选,要写的话,也只能写static

  2. 代码块分为两类,使用static修饰的叫静态代码块,没有static修饰的,叫普通代码块/非静态代码块

  3. 逻辑语句可以为任何逻辑语句(输入,输出,方法调用,循环,判断等)

  4. ;号可以写上,也可以忽略

8.3好处

  1. 相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作

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

  3. 代码演示

public class CodeBlock01 {
    public static void main(String[] args) {
​
        Movie movie = new Movie("你好,李焕英");
        System.out.println("===============");
        Movie movie2 = new Movie("唐探3", 100, "陈思诚");
    }
}
​
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("Movie(String name) 被调用...");
        this.name = name;
    }
​
    public Movie(String name, double price) {
​
        this.name = name;
        this.price = price;
    }
​
    public Movie(String name, double price, String director) {
​
        System.out.println("Movie(String name, double price, String director) 被调用...");
        this.name = name;
        this.price = price;
        this.director = director;
    }
}
​

8.4小细节

  1. static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次。如果是是普通代码块,每创建一个对象,就执行

  2. 类什么时候被加载

    • 创建对象实例化时(new)

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

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

  3. 普通的代码块,在创建对象实例化时,会被隐式的调用。

    被创建一次,就会调用一次。

    如果使用类的静态成员时,普通代码块并不会执行。

小结

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

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

  3. 类加载有三种情况,极为重要

难点:

  1. 创建一个对象时,在一个类调用顺序:

    • 调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用)

    • 调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按定义顺序调用)

  2. 构造器的最前面其实隐含了super()和调用普通代码块,静态相关的代码块,属性初始化,在类加载时,就执行完毕,异常是优于构造器和普通代码块执行的

    class A{
        public A(){//构造器
            //这里有隐藏的执行要求
            //(1)super();
            //(2)调用普通代码块的
            System.out.println("ok")
            
        }
    }
    public class CodeBlockDetail03 {
        public static void main(String[] args) {
            new BBB();//(1)AAA的普通代码块(2)AAA() 构造器被调用(3)BBB的普通代码块(4)BBB() 构造器被调用
        }
    }
    
    class AAA { //父类Object
        {
            System.out.println("AAA的普通代码块");
        }
        public AAA() {
            //(1)super()
            //(2)调用本类的普通代码块
            System.out.println("AAA() 构造器被调用....");
        }
    }
    
    class BBB extends AAA  {
        {
            System.out.println("BBB的普通代码块...");
        }
        public BBB() {
            //(1)super()
            //(2)调用本类的普通代码块
            System.out.println("BBB() 构造器被调用....");
        }
    }

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

    1. 父类的静态代码块和静态属性(优先级一样,按定义顺序执行)

    2. 子类的静态代码块和静态属性(优先级一样,按定义顺序执行)

    3. 父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)

    4. 父类的构造方法

    5. 子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)

    6. 子类的构造方法

      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
          }
      }

4.静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员。

9.final关键字

9.1基本介绍

final中文意思:最后的,最终的。

final可以修饰类,属性,方法和局部变量

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

  1. 当不希望被继承时,可以用final修饰

  2. 当不希望父类的某个方法被子类覆盖/重写(override)时,可以用final关键字修饰

  3. 当不希望类的某个属性的值被修改,可以用final修饰

  4. 当不希望某个局部变量被修改,可以使用final修饰

9.2注意事项

  1. final修饰的属性又叫常量,一般用XX_XX_XX来命名

  2. final修饰的属性在定义时,必须赋初值,并且以后不能再修改,赋值可以在如下位置之一[选择一个位置赋值即可]:

    1.定义时:如 public final double TAX_RATE=0.08;

    1. 在构造器中

      3.. 在代码块中

class AA { 

/*

\1. 定义时:如 public final double TAX_RATE=0.08; 

\2. 在构造器中 

\3. 在代码块中 

*/ 

public final double TAX_RATE = 0.08;//1.定义时赋值 

public final double TAX_RATE2 ; 

public final double TAX_RATE3 ; 

public AA() {//构造器中赋值 

TAX_RATE2 = 1.1; 

}

{//在代码块赋值 

TAX_RATE3 = 8.8; 

} 

}

3.如果final修饰的属性是静态的,则初始化的位置只能是

  • 定义时

  • 在静态代码块 不能在构造器中赋值

4.final类不能继承,但是可以实例化对象

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

6.一般来说,如果一个类已经时final类了,就没有必要再将方法修饰成final方法

7.final不能修饰构造方法

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

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

10.抽象类

10.1基本介绍

我们再去写一个父类的时候,我们有些方法不知道如何去写,写了没有实际的意义,可以将其声明为抽象方法,这个类就是抽象类,会让子类去实现。

: 父类方法不确定性的问题

//===> 考虑将该方法设计为抽象(abstract)方法

//===> 所谓抽象方法就是没有实现的方法

//===> 所谓没有实现就是指,没有方法体

//===> 当一个类中存在抽象方法时,需要将该类声明为 abstract 类

//===> 一般来说,抽象类会被继承,有其子类来实现抽象方法.

问题说明:写了没有意义,难道就不能不去写吗?

答:不能,因为是在父类没有实际的意义,但是当子类调用的时候就产生了作用。如:Animal中的eat()方法,动物是个物种不知道吃啥,但是其子类时知道吃啥的呀!

10.2细节

  1. 用abstract关键字来修饰一个类时,这个类就叫抽象类

    访问修饰符 abstract 类名{ }

  2. 用abstract关键字来修饰一个方法时,这个方法就是抽象方法

    访问修饰符 abstract 返回类型 方法名(参数列表);没有方法体

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

  4. 抽象类不能被实例化

  5. 抽象类不一定要包含abstract方法。也就是说,抽象类可以没有abstract方法

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

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

  8. 抽象类可以有任意成员[抽象类的本质还是类],比如:非抽象方法,构造器,静态属性

  9. 抽象方法不能有主题,即不能实现

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

  11. 抽象方法不能使用private,final,static来修饰,因为这些关键字都是和重写相违背的

    final是不能被继承,static关键字和方法重写无关,private的方法不能重写

11.接口

11.1基本介绍

接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,在根据具体情况把这些方法写出来。

语法:

interface 接口名{

属性

抽象方法}

class 类名 implements 接口{

自己属性;

自己方法;

必须实现的接口的抽象方法;}

jdk8.0后接口类可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现

11.2注意事项

  1. 接口不能被实例化

  2. 接口中的所有方法是public方法,接口中抽象方法,可以不用abstract修饰,例如:

    void aaa();

    实际上是 abstract void aaa();

  3. 一个普通类实现接口,就必须将该接口的所有方法都实现。

  4. 抽象类实现接口,可以不用实现接口的方法

  5. 一个类同时可以实现多个接口

  6. 接口中的属性,只能是final的,而且是public static final 修饰符。比如:int a=1;实际上是:public static final int a=1;(必须初始化)

  7. 接口中属性的访问形式:接口名.属性名

  8. 接口不能继承其他的类。但是可以继承多个别的接口

  9. 接口的修饰符只能是public和默认,这点和类的修饰符是一样的。

11.3接口和继承的区别

1.继承的价值主要在于:解决代码的复用性和可维护性。

接口的价值主要在于:设计,设计好各种规范(方法),让其他类去实现这些方法,即更加的灵活

2.接口比继承更加灵活

接口比继承更加灵活,继承是满足is-a的关系,而接口只需满足like-a的关系。

例如:is-a猫是一种动物,

like-a猫可以想小鸟一样飞翔

3.接口在一定程序上实现代码解耦[即:接口规范性+动态绑定机制]

11.4接口和抽象的区别

抽象类是将具有相同或相似特点的对象中相同的部分抽取出来形成的,它是一个抽象的概念,他本质上是一类事物,一个类只能继承一个抽象类。

接口:

它是一种规范,更多的是强调动作和行为,它是将多个对象的行为抽取出来形成的,一个类可以实现多个接口

12内部类

如果定义类在局部位置(方法中/代码块) :(1) 局部内部类 (2) 匿名内部类

定义在成员位置 (1) 成员内部类 (2) 静态内部类

12.1基本介绍

一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类。嵌套其他类的类称为外部类。是我们类的第五大成员[属性,方法,构造器,代码块,内部类],内部类最大的特点就是可以直接访问私有属性,并且可以体现类和鱼类之间的包含关系,注意:内部类是学习的难点,同时也是重点,后面看底层源码,有大量的内部类

12.2基本语法

class Outer{//外部类
    class Inner{//内部类
        
    }
}
class Other{//外部其他类
    
}

12.3内部类的分类

  1. 定义在外部类局部位置上(比如方法内/代码块):

    • 局部内部类(有类名)

    • 匿名内部类(没有类名,重点!!!!!)

  2. 定义在外部类的成员位置上:

    • 成员内部类(没用static修饰)

    • 静态内部类(使用static修饰)

12.4局部内部类的使用

说明:局部内部类是定义在外部类的局部变量,比如方法中,并且有类名。

  1. 可以直接访问外部类的所有成员,包含私有的

  2. 不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的,但是可以使用final修饰,因为局部变量也可以使用final

  3. 作用域:仅仅在定义它的方法或代码块中。

  4. 局部内部类-----访问--------->外部内部类[访问方式:直接访问]

  5. 外部类---访问---->局部内部类的成员

    访问方式:创建对象,在访问(注意:必须在作用域内)

    记住:

    • 局部内部类定义在方法中/代码块

    • 作用域在方法体或者代码块中

    • 本质仍然是一个类

  6. 外部内部类不能访问局部内部类------不能访问------>局部内部类(因为局部内部类地位是一个局部变量)

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

    System.out.println("外部类的n2="+外部类名.this.n2);

12.5匿名内部类

12.5.1基本介绍

  1. 本质时类

  2. 内部类

  3. 该类没有名字

  4. 同时是一个对象

说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名

12.5.1.1自我理解

想使用IA接口,并创建对象,但是一个一个创建类有点麻烦,因为创建的类可能只使用一次,所有就有了匿名内部类。

例如接口创建一个匿名内部类:

IA tiger = new IA() {
            @Override
            public void cry() {
                System.out.println("老虎叫唤...");
            }
        };

其实在底层会进行这个类的创建和接口的实现,而 IA tiger这一步就是给这个匿名内部类一个实例化对象

   
         class Outer04$1 implements IA {
                @Override
                public void cry() {
                    System.out.println("老虎叫唤...");
                }
            }

类创建一个匿名内部类:

Father father = new Father("jack"){

            @Override
            public void test() {
                System.out.println("匿名内部类重写了test方法");
            }
        };
class Outer04$2 extends Father{
                @Override
                public void test() {
                    System.out.println("匿名内部类重写了test方法");
                }
            }

12.5.2基本语法

new 类或接口(参数列表){
			类体		
}

12.5.3实例说明

​
/**
 * 演示匿名内部类的使用
 */
public class AnonymousInnerClass {
    public static void main(String[] args) {
        Outer04 outer04 = new Outer04();
        outer04.method();
    }
}
​
class Outer04 { //外部类
    private int n1 = 10;//属性
    public void method() {//方法
        //基于接口的匿名内部类
        //解读
        //1.需求: 想使用IA接口,并创建对象
        //2.传统方式,是写一个类,实现该接口,并创建对象
        //3.需求是 Tiger/Dog 类只是使用一次,后面再不使用
        //4. 可以使用匿名内部类来简化开发
        //5. tiger的编译类型 ? IA
        //6. tiger的运行类型 ? 就是匿名内部类  Outer04$1
        /*
            我们看底层 会分配 类名 Outer04$1
            class Outer04$1 implements IA {
                @Override
                public void cry() {
                    System.out.println("老虎叫唤...");
                }
            }
         */
        //7. jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1实例,并且把地址
        //   返回给 tiger
        //8. 匿名内部类使用一次,就不能再使用
        IA tiger = new IA() {
            @Override
            public void cry() {
                System.out.println("老虎叫唤...");
            }
        };
        System.out.println("tiger的运行类型=" + tiger.getClass());
        tiger.cry();
        tiger.cry();
        tiger.cry();
​
//        IA tiger = new Tiger();
//        tiger.cry();
​
        //演示基于类的匿名内部类
        //分析
        //1. father编译类型 Father
        //2. father运行类型 Outer04$2
        //3. 底层会创建匿名内部类
        /*
            class Outer04$2 extends Father{
                @Override
                public void test() {
                    System.out.println("匿名内部类重写了test方法");
                }
            }
         */
        //4. 同时也直接返回了 匿名内部类 Outer04$2的对象
        //5. 注意("jack") 参数列表会传递给 构造器
        Father father = new Father("jack"){
​
            @Override
            public void test() {
                System.out.println("匿名内部类重写了test方法");
            }
        };
        System.out.println("father对象的运行类型=" + father.getClass());//Outer04$2
        father.test();
​
        //基于抽象类的匿名内部类
        Animal animal = new Animal(){
            @Override
            void eat() {
                System.out.println("小狗吃骨头...");
            }
        };
        animal.eat();
    }
}
​
interface IA {//接口
    public void cry();
}
//class Tiger implements IA {
//
//    @Override
//    public void cry() {
//        System.out.println("老虎叫唤...");
//    }
//}
//class Dog implements  IA{
//    @Override
//    public void cry() {
//        System.out.println("小狗汪汪...");
//    }
//}
​
class Father {//类
    public Father(String name) {//构造器
        System.out.println("接收到name=" + name);
    }
    public void test() {//方法
    }
}
​
abstract class Animal { //抽象类
    abstract void eat();
}
​
​

12.6注意事项

  1. 匿名内部类的语法比较特殊,请大家注意,因为匿名内部类既是一个类的定义,同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出来这个特点,因此可以调用匿名内部类方法

  2. 可以直接访问外部类的所有成员,包含私有的

  3. 不能添加访问修饰符,因为它的地位就是一个局部变量

  4. 作用域:仅仅在定义它的方法或代码块中

  5. 匿名内部类----访问------>外部类成员[访问方式:直接访问]

  6. 外部类------不能访问------>匿名内部类(因为匿名内部类地位就是一个局部变量)

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

package frame.基础;
​
​
public class Text01 {
    public static void main(String[] args) {
        CellPhone cell = new CellPhone();
cell.alar(new Bell() {
    @Override
    public void ring() {
        System.out.println("懒猪起床了");
    }
});
cell.alar(new Bell() {
    @Override
    public void ring() {
        System.out.println("xdm,上课了");
    }
});
    }
​
}
interface Bell{
    void ring();
}
class CellPhone {
​
    public void alar(Bell bell){
bell.ring();
    }
​
}

13.内部类

13.1成员使用

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

  1. 可以直接访问外部类的所有成员,包含私有的

  2. 可以添加任意访问修饰符(public,protected,默认,private),因为他的地位就是一个成员

  3. 作用域

    和外部类的其他成员一样,为整个类体,在外部类的成员方法中创建成员内部类对象,在调用方法

  4. 成员内部类----访问------>外部类成员(比如:属性)[直接访问]

  5. 外部类-----访问------->成员内部类(说明)

    访问方式:创建对象,在访问

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

    //外部其他类,使用成员内部类的三种方式 
    ​
    //老韩解读 
    ​
    // 第一种方式 
    ​
    // outer08.new Inner08(); 相当于把 new Inner08()当做是 outer08 成员 
    ​
    // 这就是一个语法,不要特别的纠结. 
    ​
    Outer08.Inner08 inner08 = outer08.new Inner08(); 
    ​
    inner08.say(); 
    ​
    // 第二方式 在外部类中,编写一个方法,可以返回 Inner08 对象 
    ​
    Outer08.Inner08 inner08Instance = outer08.getInner08Instance(); 
    ​
    inner08Instance.say();

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

13.2静态内部类使用

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

  1. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员

  2. 可以添加任意访问修饰符(Public,protectded,默认,private),因为它的地位就是一个成员。

  3. 作用域:同其他的成员,为整个类体

  4. 静态内部类---访问--->外部类(比如:静态属性)【访问方式:直接访问所有静态成员】

  5. 外部类----访问------>静态内部类 访问方式:创建对象,在访问

  6. 外部其他类-----访问------>静态内部类

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

14.枚举

14.1枚举的引入

当我们需要一组固定的值,并且这一组值不会去被修改,这个时候就会引入枚举这个方法

14.2自定义枚举

  1. 不需要提供setXxx方法,因为枚举对象通常为只读

  2. 对枚举对象/属性使用final+static共同修饰,实现底层优化

  3. 枚举对象名通常使用全部大写,常量的命名规范

  4. 枚举对象根据需要,也可以有多个属性

public class Enumeration02 {
    public static void main(String[] args) {
        System.out.println(Season.AUTUMN);
        System.out.println(Season.SPRING);
    }
}
​
//演示字定义枚举实现
class Season {//类
    private String name;
    private String desc;//描述
​
    //定义了四个对象, 固定.
    public static final Season SPRING = new Season("春天", "温暖");
    public static final Season WINTER = new Season("冬天", "寒冷");
    public static final Season AUTUMN = new Season("秋天", "凉爽");
    public static final Season SUMMER = new Season("夏天", "炎热");
​
​
    //1. 将构造器私有化,目的防止 直接 new
    //2. 去掉setXxx方法, 防止属性被修改
    //3. 在Season 内部,直接创建固定的对象
    //4. 优化,可以加入 final 修饰符
    private Season(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }
​
    public String getName() {
        return name;
    }
​
    public String getDesc() {
        return desc;
    }
​
    @Override
    public String toString() {
        return "Season{" +
                "name='" + name + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }
}

14.3 enum关键字实现枚举

14.3.1 enum 关键字实现枚举注意事项

\1) 当我们使用 enum 关键字开发一个枚举类时,默认会继承 Enum 类, 而且是一个 final 类[如何证明],老师使用 javap 工

具来演示

\2) 传统的 public static final Season2 SPRING = new Season2("春天", "温暖"); 简化成 SPRING("春天", "温暖"), 这里必

须知道,它调用的是哪个构造器.

\3) 如果使用无参构造器 创建 枚举对象,则实参列表和小括号都可以省略

\4) 当有多个枚举对象时,使用,间隔,最后有一个分号结尾

\5) 枚举对象必须放在枚举类的行首

public class Enumeration03 {
    public static void main(String[] args) {
        System.out.println(Season2.AUTUMN);
        System.out.println(Season2.SUMMER);
    }
}
//演示使用enum关键字来实现枚举类
enum  Season2 {//类
​
​
    //定义了四个对象, 固定.
//    public static final Season SPRING = new Season("春天", "温暖");
//    public static final Season WINTER = new Season("冬天", "寒冷");
//    public static final Season AUTUMN = new Season("秋天", "凉爽");
//    public static final Season SUMMER = new Season("夏天", "炎热");
    //如果使用了enum 来实现枚举类
    //1. 使用关键字 enum 替代 class
    //2. public static final Season SPRING = new Season("春天", "温暖") 直接使用
    //   SPRING("春天", "温暖") 解读 常量名(实参列表)
    //3. 如果有多个常量(对象), 使用 ,号间隔即可
    //4. 如果使用enum 来实现枚举,要求将定义常量对象,写在前面
    //5. 如果我们使用的是无参构造器,创建常量对象,则可以省略 ()
    SPRING("春天", "温暖"), WINTER("冬天", "寒冷"), AUTUMN("秋天", "凉爽"),
    SUMMER("夏天", "炎热")/*, What()*/;
​
    private String name;
    private String desc;//描述
​
    private Season2() {//无参构造器
​
    }
​
    private Season2(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }
​
    public String getName() {
        return name;
    }
​
    public String getDesc() {
        return desc;
    }
​
    @Override
    public String toString() {
        return "Season{" +
                "name='" + name + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }
}
​
​

14.4 enum 常 用方法说明

\1) toString:Enum 类已经重写过了,返回的是当前对象

名,子类可以重写该方法,用于返回对象的属性信息

\2) name:返回当前对象名(常量名),子类中不能重写

\3) ordinal:返回当前对象的位置号,默认从 0 开始

\4) values:返回当前枚举类中所有的常量

\5) valueOf:将字符串转换成枚举对象,要求字符串必须

为已有的常量名,否则报异常!

\6) compareTo:比较两个枚举常量,比较的就是编号!

​
public class EnumMethod {
    public static void main(String[] args) {
        //使用Season2 枚举类,来演示各种方法
        Season2 autumn = Season2.AUTUMN;
​
        //输出枚举对象的名字
        System.out.println(autumn.name());
        //ordinal() 输出的是该枚举对象的次序/编号,从0开始编号
        //AUTUMN 枚举对象是第三个,因此输出 2
        System.out.println(autumn.ordinal());
        //从反编译可以看出 values方法,返回 Season2[]
        //含有定义的所有枚举对象
        Season2[] values = Season2.values();
        System.out.println("===遍历取出枚举对象(增强for)====");
        for (Season2 season: values) {//增强for循环
            System.out.println(season);
        }
​
        //valueOf:将字符串转换成枚举对象,要求字符串必须•为已有的常量名,否则报异常
        //执行流程
        //1. 根据你输入的 "AUTUMN" 到 Season2的枚举对象去查找
        //2. 如果找到了,就返回,如果没有找到,就报错
        Season2 autumn1 = Season2.valueOf("AUTUMN");
        System.out.println("autumn1=" + autumn1);
        System.out.println(autumn == autumn1);
​
        //compareTo:比较两个枚举常量,比较的就是编号
        //老韩解读
        //1. 就是把 Season2.AUTUMN 枚举对象的编号 和 Season2.SUMMER枚举对象的编号比较
        //2. 看看结果
        /*
        public final int compareTo(E o) {
​
            return self.ordinal - other.ordinal;
        }
        Season2.AUTUMN的编号[2] - Season2.SUMMER的编号[3]
         */
        System.out.println(Season2.AUTUMN.compareTo(Season2.SUMMER));
​
        //补充了一个增强for
//        int[] nums = {1, 2, 9};
//        //普通的for循环
//        System.out.println("=====普通的for=====");
//        for (int i = 0; i < nums.length; i++) {
//            System.out.println(nums[i]);
//        }
//        System.out.println("=====增强的for=====");
//        //执行流程是 依次从nums数组中取出数据,赋给i, 如果取出完毕,则退出for
//        for(int i : nums) {
//            System.out.println("i=" + i);
//        }
    }
}
​

14.5注意事项

\1)使用 enum 关键字后,就不能再继承其它类了,因为 enum 会隐式继承 Enum,而 Java 是单继承机制。

\2) 枚举类和普通类一样,可以实现接口,如下形式。

enum 类名 implements 接口 1,接口 2{}

14.6lamda

package frame.基础;
​
/**
 * 海绵hong
 * version 1.0
 */
@SuppressWarnings({"all"})
public class Text03 {
    public static void main(String[] args) {
        sss(3,5,new Ip() {
            @Override
            public int fun(int a, int b) {
                return a+b;
            }
        });
        sss(3,5,(a,b)-> a+b);//(a,b)-> {a+b};只有一条语句可以去除大括号
    }
    public static void sss(int a,int b,Ip ip){
        System.out.println(ip.fun(a,b));
    }
}
interface Ip{
    int fun(int a, int b);
}

15.注解

15.1注解的理解

\1) 注解(Annotation)也被称为元数据(Metadata),用于修饰解释 包、类、方法、属性、构造器、局部变量等数据信息。

\2) 和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。

\3) 在 JavaSE 中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在 JavaEE 中注解占据了更重要的角

色,例如用来配置应用程序的任何切面,代替 java EE 旧版中所遗留的繁冗代码和 XML 配置等。

15.2三个基本的 Annotation:

\1) @Override: 限定某个方法,是重写父类方法, 该注解只能用于方法

\2) @Deprecated: 用于表示某个程序元素(类, 方法等)已过时 (即不推荐使用,但是可以使用)@Deprecated 可以做版本升级过渡使用

\3) @SuppressWarnings: 抑制编译器警告

@SuppressWarnings({"all"})

  1. 当我们不希望看到这些警告的时候,可以使用 SuppressWarnings 注解来抑制警告信息

  2. 在{""} 中,可以写入你希望抑制(不显示)警告信息

  3. 可以指定的警告类型有

    all,抑制所有警告

15.3元注解

15.3.1@Retention

只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 可以保留多长时间, @Rentention 包含一个 RetentionPolicy 类型的成员变量, 使用 @Rentention 时必须为该 value 成员变量指定值:

@Retention 的三种值

\1) RetentionPolicy.SOURCE: 编译器使用后,直接丢弃这种策略的注释

\2) RetentionPolicy.CLASS: 编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 不会保留注解。 这是默认 值

\3) RetentionPolicy.RUNTIME:编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 会保留注解. 程序可以 通过反射获取该注解

15.3.2@Targe

用于修饰注解定义,用于指定被修饰的注解

15.3.3@Documented

@Documented :用于指定被该元注解修饰的注解类将被javadoc根据提取成文档,即在生成文档是,可以看到该注解

15.3.4@Inherited 注解

被它修饰的注解将具有继承性,如果某个类使用了被@Inherited修饰的注解,则其子类将自动具有该注解

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自学Java的知识盲点(面向对象编程) 的相关文章

  • Java中ArrayList的交集和并集

    有什么方法可以做到这一点吗 我正在寻找 但没有找到 另一个问题 我需要这些方法 以便我可以过滤文件 有些是AND过滤器 有些是OR过滤器 就像集合论中的那样 所以我需要根据所有文件和保存这些文件的联合 相交 ArrayList 进行过滤 我
  • Spring应用中Eureka健康检查的问题

    我正在开发一个基于 Spring 的应用程序 其中包含多个微服务 我的一个微服务充当尤里卡服务器 到目前为止一切正常 在我所有其他微服务中 用 EnableEurekaClient 我想启用这样的健康检查 应用程序 yml eureka c
  • org.apache.hadoop.security.AccessControlException:客户端无法通过以下方式进行身份验证:[TOKEN,KERBEROS] 问题

    我正在使用 java 客户端通过 Kerberos 身份验证安全访问 HDFS 我尝试打字klist在服务器上 它显示已经存在的有效票证 我收到的异常是客户端无法通过以下方式进行身份验证 TOKEN KERBEROS 帮助将不胜感激 这是一
  • 如何在java中将一个数组列表替换为另一个不同大小的数组列表

    我有两个大小不同的数组列表 如何从此替换 ArrayList
  • 过滤两次 Lambda Java

    我有一个清单如下 1 2 3 4 5 6 7 和 预期结果必须是 1 2 3 4 5 6 7 我知道怎么做才能到7点 我的结果 1 2 3 4 5 6 我也想知道如何输入 7 我添加了i gt i objList size 1到我的过滤器
  • HSQL - 识别打开连接的数量

    我正在使用嵌入式 HSQL 数据库服务器 有什么方法可以识别活动打开连接的数量吗 Yes SELECT COUNT FROM INFORMATION SCHEMA SYSTEM SESSIONS
  • Pig Udf 显示结果

    我是 Pig 的新手 我用 Java 编写了一个 udf 并且包含了一个 System out println 其中的声明 我必须知道在 Pig 中运行时该语句在哪里打印 假设你的UDF 扩展了 EvalFunc 您可以使用从返回的 Log
  • 如何获取之前的URL?

    我需要调用我的网络应用程序的 URL 例如 如果有一个从 stackoverflow com 到我的网站 foo com 的链接 我需要 Web 应用程序 托管 bean 中的 stackoverflow 链接 感谢所有帮助 谢谢 并不总是
  • 将流转换为 IntStream

    我有一种感觉 我在这里错过了一些东西 我发现自己做了以下事情 private static int getHighestValue Map
  • java.lang.IllegalStateException:提交响应后无法调用 sendRedirect()

    这两天我一直在尝试找出问题所在 我在这里读到我应该在代码中添加一个返回 我做到了 但我仍然得到 java lang IllegalStateException Cannot call sendRedirect after the respo
  • 无法创建请求的服务[org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]-MySQL

    我是 Hibernate 的新手 我目前正在使用 Spring boot 框架并尝试通过 hibernate 创建数据库表 我知道以前也问过同样的问题 但我似乎无法根据我的环境找出如何修复错误 休眠配置文件
  • Eclipse Maven Spring 项目 - 错误

    I need help with an error which make me crazy I started to study Java EE and I am going through tutorial on youtube Ever
  • jdbc mysql loginTimeout 不起作用

    有人可以解释一下为什么下面的程序在 3 秒后超时 因为我将其设置为在 3 秒后超时 12秒 我特意关闭了mysql服务器来测试mysql服务器无法访问的这种场景 import java sql Connection import java
  • volatile、final 和synchronized 安全发布的区别

    给定一个带有变量 x 的 A 类 变量 x 在类构造函数中设置 A x 77 我们想将 x 发布到其他线程 考虑以下 3 种变量 x 线程安全 发布的情况 1 x is final 2 x is volatile 3 x 设定为同步块 sy
  • 尝试将 Web 服务部署到 TomEE 时出现“找不到...的 appInfo”

    我有一个非常简单的项目 用于培训目的 它是一个 RESTful Web 服务 我使用 js css 和 html 创建了一个客户端 我正在尝试将该服务部署到 TomEE 这是我尝试部署时遇到的错误 我在这里做错了什么 刚刚遇到这个问题 我曾
  • 干净构建 Java 命令行

    我正在使用命令行编译使用 eclipse 编写的项目 如下所示 javac file java 然后运行 java file args here 我将如何运行干净的构建或编译 每当我重新编译时 除非删除所有内容 否则更改不会受到影响 cla
  • 找不到符号 NOTIFICATION_SERVICE?

    package com test app import android app Notification import android app NotificationManager import android app PendingIn
  • 使用反射覆盖最终静态字段是否有限制?

    在我的一些单元测试中 我在最终静态字段上的反射中遇到了奇怪的行为 下面是说明我的问题的示例 我有一个基本的 Singleton 类 其中包含一个 Integer public class BasicHolder private static
  • 长轮询会冻结浏览器并阻止其他 ajax 请求

    我正在尝试在我的中实现长轮询Spring MVC Web 应用程序 http static springsource org spring docs 2 0 x reference mvc html但在 4 5 个连续 AJAX 请求后它会
  • 如果没有抽象成员,基类是否应该标记为抽象?

    如果一个类没有抽象成员 可以将其标记为抽象吗 即使没有实际理由直接实例化它 除了单元测试 是的 将不应该实例化的基类显式标记为抽象是合理且有益的 即使在没有抽象方法的情况下也是如此 它强制执行通用准则来使非叶类抽象 它阻止其他程序员创建该类

随机推荐

  • 小孩机器人编程真的有用吗

    小孩机器人编程真的有用吗 很多的家长在培养孩子的学习的时候 是十分的认真耐心的 他们会给孩子选择一些能够有利于孩子成长的课程 就拿现在很多的家长想要孩子去学习机器人编程的课程来说 有的家长对于小孩机器人编程真的有用吗并不是很清楚 今天我们就
  • Docker(六)----Swarm搭建Docker集群

    一 什么是Swarm Swarm这个项目名称特别贴切 在Wiki的解释中 Swarm behavior是指动物的群集行为 比如我们常见的蜂群 鱼群 秋天往南飞的雁群都可以称作Swarm behavior Swarm项目正是这样 通过把多个D
  • 数据结构---链表

    目录 链表的概念 封装单项链表 封装链表结构 append方法 追加元素 toString方法 转字符串 insert方法 插入元素 get方法 获取元素 indexof 获取索引 update修改某个位置的元素 removeAt方法 删除
  • SQL 日期比较 datediff

    datediff date1 date2 返回 date1 date2的相差天数 用在select语句 select datediff date select max start time from tb user video log da
  • 史上最强内网渗透知识点总结

    https mp weixin qq com s biz MzI5MDQ2NjExOQ mid 2247487491 idx 1 sn 270336c6cca79b4a4e5d777d41ce71b7 chksm ec1e202bdb69a
  • 银河麒麟操作系统v10安装时间

    银河麒麟操作系统安装时间方法1sudo date r var log installer 方法2df Th 然后sudo dumpe2fs dev nvme0n1p3 grep i created
  • sql的递归查询

    在oracle中通过connect by prior来实现递归查询 分类 Oracle随笔 2007 02 16 09 13 11278人阅读 评论 3 收藏 举报 connect by 是结构化查询中用到的 其基本语法是 select f
  • vue3 组件传值之 props 与 attrs 的区别

    最近在学习 vue3 整理了一些学习笔记 如果有人看到 并发现我有写的不对的地方 欢迎指正 用过 vue 组件传值的小伙伴都知道 props 这个属性 而 attrs 属性可以看做 props 的加强版 用来简化 vue 组件传值 那么这两
  • 条件变量(condition variable)详解

    原理 假设我们需要解决这样一个问题 一个列表记录需要处理的任务 一个线程往此列表添加任务 一个线程processTask处理此列表中的任务 这个问题的一个关键点在于processTask怎么判断任务列表不为空 一般有两种方法 一 proce
  • Mathematica的Combinatorica`程序包来研究分拆

    文章目录 引论 步骤 0x00 导入程序包 0x01 Partitions 0x02 Compositions Log 引论 分拆可以看我的这篇文章 在线的Combinatorica 程序包文档可以看这个 在线的Combinatorica
  • 我所理解的RSA加密算法

    RSA简介 非对称加密算法 有一对公私钥组成 1977年由三位数学家Rivest Shamir 和 Adleman 设计了一种算法 没错RSA是三个人名字的首字母 密钥越长越难破解 1024位目前无法破解 因此1024位的RSA密钥基本安全
  • 实现instanceof操作符

    实现instanceof操作符 const theInstanceof function object constructor if typeof object object typeof constructor function retu
  • Spark学习(文件读取路径)

    在不同的启动模式下 加载文件时的路径写法是不一样的 对于local模式下 默认就是读取本地文件 而在standlone或者yarn client 或者cluster模式下 默认读的都是hdfs文件系统 这几种模式下很难读取本地文件 这是很显
  • Qt 信号和槽的小问题(新手向)

    Qt项目报错 static assertion failed Signal and slot arguments are not compatible 信号和槽的参数不对应 例 槽函数 void A give QString a qDebu
  • 内存数据库-3-[redis]的架构原理和部署模式

    参考redis三种模式对比 Redis 是一个开源的 key value 存储系统 由于出众的性能 大部分互联网企业都用来做服务器端缓存 1 单实例模式 问题 1 内存容量有限 2 处理能力有限 3 无法高可用 Redis 在3 0版本前只
  • 我的股票项目环境配置过程记录(含python打包方法linux windows)

    股票项目从源码配置环境 V1 0 Windows 如果只是跑只需要这两个 pip3 install PyQt5 i https pypi douban com simple pip install U matplotlib pip inst
  • 直流-直流(DC-DC)变换电路

    直流 直流 DC DC 变换电路 可以将一种直流电源经过变换电路后输出另一种具有不同输出特性的直流电源 可以是一种固定电压或可调电压的直流电 按照电路拓扑结构的不同 DC DC变换电路可以分成两种形式 不带隔离变压器的DC DC变换电路和带
  • Tomcat7安装及配置教程

    Apache Tomcat7 0安装及配置教程 Apache Tomcat7 0官方网站链接 http tomcat apache org apache tomcat 7 0 73 windows x64 先解压下载的压缩包 然后在bin目
  • 使用express封装一个简单的http代理服务器以及手动设置Access-Control-Allow-Origin解决跨域问题

    一 跨域是什么 先来了解一下什么是跨域 才能知道如何解决跨域问题 跨域 出于浏览器的同源策略限制 使浏览器不能执行其他网站的脚本 同源策略是浏览器对 javascript 施加的安全限制 所谓同源就是指在同一个域内 就是两个地址具有相同的协
  • 自学Java的知识盲点(面向对象编程)

    目录 1 类和对象 1 1对象 属性 行为 1 1 1属性 成员变量 1 2类和对象的内存分配机制 1 3构造方法 1 3 1this关键字 1 4访问修饰符 2 封装 2 1定义 3 继承 ctrl h可以看继承关系 3 1基本介绍 本质