1. static
1.1. static修饰的变量
在一个类中用static修饰的变量,属于类变量,在内存中只有一份,会被类的全部对象共享,所以可以用类名直接调用,即类名.类变量
用static修饰的变量,属于类变量,会被类的全部对象共享,所以无论怎么修改,调用后都是最后一次修改后的值
1.2. static修饰的方法
工具类
类方法可以直接使用类.方法
调用,可以节省内存,而实例调用方法,需要先创建一个对象,而每创建一个对象会消耗内存。
工具类的构造器应该做私有化处理,(在一个类中默认有一个空参构造器)
用static修饰的变量或者方法都是类的,下面为其注意事项。
1.3. 代码块
被static修饰的代码块,是类代码块,在加载类时,就会执行一次,未被修饰的是实例代码块(也可以叫做对象代码块)创建一个对象时,就会被执行一次,用来完成对象的初始化,在构造器前执行。
1.4. 单例设计模式
Java已有单例模式,可参考Runtime
1.4.1. 饿汉式单例模式
懒汉式与饿汉式的区别
懒汉式与饿汉式的区别_懒汉式和饿汉式的区别-CSDN博客
1.4.2. 懒汉式单例模式
2. 继承
Java中的继承是单继承,不支持多继承,但是可以多层继承。
2.1. Object类
Object类是所有类都会继承的类
2.2. 方法重写
2.3. 子类构造器
子类构造器默认都会继承父类的无参构造器,所以父类必须存在一个无参构造器,如果没有,则会报错。
但是如果父类存在一个有参构造器,可以通过super(xxx)去继承父类的有参构造器。
2.4. this(...)
class A(String name,int age){ this.name = name; this.age = age; this.college = "sias"; //后面的值是创建对象时,构造器传进来的参数。 }
this()和super()区别:
- this()和super()都必须放在构造器中的第一行。
- this()是用来调用本类内的其他构造器
- super()是用来调用父类的构造器,为对象中包含父类这部分的成员变量赋值。
3. 多态
多态是在继承或者实现一种现象,表现为对象多态和行为多态
3.1. 多态类型转换
多态类型转换分为自动类型转换和强制类型转换
强制类型转换前应该先用instanceof xxx进行判断。
4. final
5. 抽象类
用abstract修饰的类就叫做抽象类,抽象方法不能有方法体
抽象抽象,何为抽象就是不能具体化,所以有方法,但是没有方法体
抽象类的设计,是为了丰富子类,父类只管设计,子类负责实现具体内容,比如都是人,把人设计为抽象类,然后用子类(老师,学生等)去重写实现人这个父类(抽象类)的方法
所以抽象类不能创建对象,只能让子类去继承,子类继承之后,要重写所有的抽象类中的方法。否则这个类也必须声明为抽象类。
在开发中,抽象类不是必须设计的
抽象类的设计,是为了丰富子类,父类只管设计,子类负责实现具体内容,比如都是人,把人设计为抽象类,然后用子类(老师,学生等)去重写实现人这个父类(抽象类)的方法
5.1. 模板方法设计模式
用抽象类设计模板方法世纪模式,这个类里面有两个方法,一个是应该被final修饰的模板方法,一个是应该被子类重写的抽象方法。
模板方法可以使用final关键字修饰,禁止子类修改。
6. 接口
- 接口弥补了单继承的不足
- 接口不能创建对象,接口只能被实现
- 接口不能创建对象,但是可以用匿名类去实现接口,创建一个匿名类,从而创建对象(参考链接:接口可以创建对象、实例化吗?_接口创建对象-CSDN博客)
接口默认的变量(即成员变量)是常量
成员方法是抽象方法,所以没有方法体
接口可以理解为是一种特殊的抽象类,所以不能有构造器和方法体
实现类实现多个接口,必须重写全部抽象方法,否则实现类需要定义成抽象类
jdk8开始新增的接口特性
7. 枚举类 enum
枚举类每一个常量对应一个对象
枚举类的构造器是私有的,因此枚举类对外不能创建对象
枚举都是最终类,不可以被继承
枚举类常见应用场景:
用来表示一组信息,然后作为参数进行传输
8. 内部类
Java类的五大成员(成员变量、构造器、代码块、内部类、方法)
内部类是定义在某个类内部的类
8.1. 成员内部类
成员内部类的创建需要先创建外部类的对象再创建内部类对象
8.2. 静态内部类
8.3. 局部内部类
8.4. 匿名内部类(重点)
匿名内部类编译成一个子类,然后会立即创建一个子类对象
- 匿名类使用场景1:作为参数直接传递给方法
- 匿名类就是为了简化代码。配合lambda表达式使用更好!
9. 泛型
泛型有泛型类、泛型接口、泛型方法。
泛型只支持引用数据类型,不支持基本数据类型
ArrayList<int> list = new ArrayList<>(); //xc错误的不支持基本数据类型 //但是可以通过基本数据类型对应的包装类解决 ArrayList<Integer> list1 = new ArrayList<>();
10. 集合
集合是一种容器,用来存放数据的,类似于数组,但集合的大小可变
注意有序无序重复不可重复
10.1. 单列集合 Collection
10.1.1. colletion的遍历方式
- 迭代器
Collection<String> c = new ArratList<>(); //创建集合对象 此处体现了多态性 System.out.println(c); //可以直接打印集合中的所有元素 //需要先创建迭代器对象 Iterator<String> it = c.iterator(); // it.next(); //逐个遍 历 可以直接打印 // it.next(); //这种持续遍历会报元素越界错误异常 应该采用循环遍历的方法 while(it.hasNext()){ String ele = it.next(); System.out.println(ele); }
- 增强for
可以用来遍历数组或者集合
Collection<String> c = new ArratList<>(); for(String a : c ){ sout(a); }
- lambda表达式
10.1.2. List集合
8888第八集
11. 包装类
包装类可以把基本数据类型包装成为一个个对象
解决了集合中指定泛型不能使基本数据类型的问题。
包装类具有自动装箱和自动拆箱的功能
Integer i = 12; // ArrayList<Integer> list = new ArrayList<>(); list.add(i);//自动装箱 将基本数据类型转换为对象 int res = list.get(0);
12. StringBuilder
对于字符串操作较少使用String即可,过多选择StringBuilder
13. Lambda
用于简化匿名内部类的代码
Lambda表达式并不是能简化全部匿名内部类,只能简化函数式接口
(只能有一个方法)的匿名内部类
13.1. lambda表达式简化规则
13.2. xxx引用 ::
是对lambda表达式的进一步简化
静态方法引用
实例方法引用
特定方法引用
构造器引用
14. 多线程
不管是那种线程的创建方式都需要将start方法放在子线程前面,不让还是单线程。
14.1. 多线程创建方式1:继承Thread类
14.2. 多线程创建方式2:实现Runnable接口
此方式需要定义一个任务类,实现Runnable接口
并且这种方式需要new Thread线程,将任务类对象放入new Thread方法中
14.3. 多线程创建方式3:实现Callable接口
此创建方式可以返回结果,而前面两种不能返回结果,因为run()方法都是void。
15. 动态代理