1 final 关键字修饰变量,方法,类,系统不允许为final变量重新赋值,子类不允许覆盖父类final方法,final类不能派生子类。通过final实现不可变类,不可变类让系统更安全。
2 抽象类主要作为多个类的模版,接口定义了多个类应该遵守的规范,
3 enum用于创建枚举类,枚举类是一种不能自由创建对象的类,枚举类的对象在定义类时已经固定下来。适应与季节,这样的类,创建的实例有限且确定
4 为了解决8种基本数据类型变量不能当成Object类型变量使用,Java提供了包装类的概念,为基本类型分别提供了相应的引用类型,称为包装类。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public static void main(String[] args) { Boolean b = new Boolean("dfd"); System.out.println(b.toString()); } false
5 Integer 特殊 -128 - 127 装箱有缓存
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
System.out.println(new Integer(3) == new Integer(3)); // false 不是同一个引用 Integer i1 = 9; Integer i2 = 9; System.out.println(i1 == i2); // true 缓存 Integer i3 = 1111; Integer i4 = 1111; System.out.println(i3 == i4); // false;
6 == 如果两个变量是基本类型变量,且都是数值类型(不要求类型相同)只要值相同就true,引用类型变量,必须指向同一个对象,== 不可用于比较类型上没有父子关系的两个对象。否则编译出错
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
int i = 65; char c = 'A'; double d = 65.0; System.out.println(i == c); System.out.println(i == d); String s1 = new String("hello"); String s2 = new String("hello"); System.out.println(s1 == s2); System.out.println(s1.equals(s2)); true true false true
7 常量池用于管理在编译期被确定并被保存在已编译的.class文件中的一些数据,包括关于类,方法,接口中的常量,还包括字符串常量。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
String s1 = "fengkuangjava"; String s2 = "fengkuang"; String s3 = "java"; String s4 = s2 + s3; // 不能在编译期确定 String s6 = "fengkuang" + "java"; // 可以在编译期确定 String s5 = new String("fengkuangjava"); System.out.println(s1 == s6); // true System.out.println(s1 == s4); // false System.out.println(s1 == s5); // false
8equals方法满足条件 1 自反性 x.equals(x);一定true 2 对称性 x.equals(y) true y.equals(x)也为true 3 传递性,x, y, z 4 一致性:任意x,y 如果对象中等价比较信息不变,无论调用多少此,结果保持不变,5 x != null x.equals(null) false;
9 即使某个实例为null,他也可以访问所属类成员
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class My { static int j = 0; static void text() { } public static void main(String[] args) { My m = null; m.text(); } }
10 final用于修饰类,变量,方法,表示它修饰的类,方法,变量不可变。final可以修饰成员变量,局部变量,形参。修饰的变量不可被改变,一旦获得初值,就不能重新赋值。
final修饰的成员变量必须由程序员显示指定初值。
类field ,必须在静态初始化块,或声明变量时指定初值
实例field,非静态初始化块,声明处,构造器中初始值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class My { final int i1 = 1; final int i2; { i2 = 2; } final int i3; My() { i3 = 3; } static final int i4; static { i4 = 4; } public static void main(String[] args) { My m = new My(); } }
final修饰局部变量,如果定义时没有指定值,可以在后面赋值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class My { void test(final int a) { a = 1; // error already has num; final int b; b = 0; } public static void main(String[] args) { My m = new My(); } }
11 对于final变量,满足3个条件,就是可替换宏变量 1 变量final修饰 2 定义变量时指定初值,3 初值可以在编译时确定
程序中所有遇到宏变量时,编译期间都会替换为值,
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public static void main(String[] args) { final int a = 5 + 2; //宏变量 final String book = "df" + 1; // 宏变量 final String book2 = "ffs" + String.valueOf(0); // 非宏变量,不可以在编译器确定值 String s1 = "123"; String s2 = "12"; String s3 = "3"; String s4 = s2 + s3; // 无法在编译器确定 System.out.println(s1 == s4); //false String s5 = "123"; final String s6 = "12"; final String s7 = "3"; String s8 = s6 + s7; // 无法在编译器确定 System.out.println(s5 == s8); // true }
12 final修饰的方法不能被重写。对于一个private方法,子类无法访问该方法,所以子类无法重写该方法,所以,即使使用final修饰一个private方法,依然可以在子类中定义与该方法具有相同方法名,形参列表,返回值类型的方法。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Base{ private final void test() { } } class Sub{ void test() { } }
13 不可变类:创建该类的实例后,实例的field不可改变,8种包装类和Sring类就是不可变类,创建自定义不可变类遵循规则如下
1 使用private final修饰field 2 提供带参数构造器,用于初始化field 3 仅为field提供getter()方法,4 如果有必要,重写hashCode和equals方法。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Name{ private final String first; private final String last; public Name(String first, String last) { super(); this.first = first; this.last = last; } public Name() { this.first = ""; this.last = ""; } public String getFirst() { return first; } public String getLast() { return last; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj != null && obj.getClass() == Name.class) { Name n = (Name) obj; if (n.getFirst().equals(this.getFirst()) && n.getLast().equals(this.getLast())) { return true; } } return false; } public int hashCode() { return first.hashCode() + last.hashCode() * 31; } }
缓存实例的不可变类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
private static int MAX_SIZE = 10; private static CacheImmutable[] cache = new CacheImmutable[MAX_SIZE]; private static int pos = 0; private final String name; public String getName() { return name; } public CacheImmutable(String name) { super(); this.name = name; } public static CacheImmutable valueOf(String name) { for (int i = 0; i < MAX_SIZE; i++) { if (cache[i] != null && cache[i].getName().equals(name)) { return cache[i]; } } if (pos >= MAX_SIZE) { cache[0] = new CacheImmutable(name); pos = 1; } else { cache[pos++] = new CacheImmutable(name); } return cache[pos - 1]; } @Override public int hashCode() { return name.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj != null && obj.getClass() == CacheImmutable.class) { CacheImmutable c = (CacheImmutable) obj; if (c.getName().equals(this.getName())) { return true; } } return false; } }
14 回调
某个方法一旦获得了内部类对象的引用,可以在合适的时候调用外部类实例方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class My { public static void main(String[] args) { TeachableProgrammer tp = new TeachableProgrammer("Tom"); tp.work(); tp.getTeachable().work(); } } class TeachableProgrammer extends Programmer { public TeachableProgrammer() { super(); // TODO Auto-generated constructor stub } public TeachableProgrammer(String name) { super(name); // TODO Auto-generated constructor stub } private void teach() { System.out.println(getName() + " teacher"); } private class Closure implements Teachable { @Override public void work() { // TODO Auto-generated method stub teach(); } } public Teachable getTeachable() { return new Closure(); } } interface Teachable { void work(); } class Programmer { private String name; public Programmer(String name) { super(); this.name = name; } public Programmer() { super(); // TODO Auto-generated constructor stub } public String getName() { return name; } public void work() { System.out.println(name + " progreame"); } }
15 枚举
手动实现规则1 private 构造器隐藏 2 实例public static final 3 提供一些静态方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Season { private final String name; private final String desc; public static final Season SPRING = new Season("春", "春意盎然"); public static final Season SUMMER = new Season("夏", "烈日炎炎"); public static final Season FALL = new Season("秋", "果实累累"); public static final Season WINTER = new Season("冬","冰天雪地"); public Season(String name, String desc) { super(); this.name = name; this.desc = desc; } public String getName() { return name; } public String getDesc() { return desc; } public static Season getSeason(int num) { switch (num) { case 1: return SPRING; case 2: return SUMMER; case 3: return FALL; case 4: return WINTER; default: return null; } } }
枚举类是一种特殊的类,可以有自己的field 方法,构造器,可以实现接口
枚举类和普通类不同:
1 可以实现一个或多个接口,默认继承Java.lang.Enum类,而不是Object ,2 类默认final修饰,所以不能派生子类,3 构造器使用private修饰,4 所有实例在第一行显示列出
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class My { public static void main(String[] args) { for (Seasson s : Seasson.values()) { System.out.println(s); } } } enum Seasson { SPRING, SUMMER, FALL, WINTER; }
带field枚举 实现接口枚举
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
enum Gender { MALE("男"), FEMALE("女"); private final String name; private Gender(String name) { this.name = name; } public String getName() { return name; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
enum Gender implements Info{ MALE("男") { public void info() { System.out.println("represent male"); } }, FEMALE("女") { @Override public void info() { // TODO Auto-generated method stub System.out.println("represnent female"); } }; private final String name; private Gender(String name) { this.name = name; } public String getName() { return name; } } interface Info{ void info(); }
包含抽象方法枚举类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
enum Gender{ MALE("男") { public void info() { System.out.println("represent male"); } }, FEMALE("女") { @Override public void info() { // TODO Auto-generated method stub System.out.println("represnent female"); } }; public abstract void info(); private final String name; private Gender(String name) { this.name = name; } public String getName() { return name; } }
16 垃圾回收
1 只负责回收堆内存对象,不会回收任何物理资源(数据库连接,网络) 2 无法精确控制垃圾回收运行,会在适当时候运行 3 在回收任何对象前,总会先调用finalize()方法。可能使对象复活,让引用引用该对象,导致取消回收
对象内存状态 1 可达状态,对象被创建,有一个以上的变量引用他,可通过变量调用对象field和方法。2 可恢复状态 没有任何变量引用对象,在回收对象前,系统调用finalize()方法经行资源清理,如果系统在调用方法时重新让一个引用变量引用该对象对象变为可达,否则进入不可达。3 所有引用被切断,回收对象占用资源。
对象可以被局部变量,类变量(类销毁后对象进入可恢复) 实例变量(实例销毁后对象进入可恢复)引用
强制垃圾回收
System.gc();
Runtime.getRuntime().gc();
finalize()方法特定
1 永远不要调用某个对象该方法,要交给垃圾回收机制调用2 方法何时被调用,是否被调用不确定,不要把他当成一定会调用方法 2 jvm执行该方法时,可使该对象或系统中其他对象重新变可达状态3 执行方法出现异常时,垃圾回收机制不会报告异常,程序继续执行。
由于finalize不一定会执行,如果想清理类打开的资源,不要放到finalize方法清理。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class My { private static My my = null; public void info() { System.out.println("dww"); } public static void main(String[] args) throws Exception { new My(); Runtime.getRuntime().gc(); Thread.sleep(2000); my.info(); } @Override protected void finalize() throws Throwable { // TODO Auto-generated method stub my = this; // 对象复活 } }
强引用;:就是把对象的引用直接赋给变量,如果对象有强引用,jvm必然不会回收这个对象,即使在内存不足的情况,jvm宁愿抛出outofmemeory,也不会回收这种对象。
软引用:有用但并不是必须的对象,只有在内存不足的时候才会回收该对象,时候用来实现缓存。
弱引用:描述非必须对象当jvm经行垃圾回收时,无论内存是否充足,都会回收被弱引用关联对象。
虚引用:不影响对像生命周期,虚引用引用的对像任何时候都可能被垃圾回收。虚引用必须和引用队列关联,当虚引用引用的对象被垃圾回收后,虚引用被添加到队列,
要使用这些特殊引用就不能保留对象的强引用,如果保留强引用会浪费使用这些引用好处。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
String str = new String("sdf"); SoftReference<String> s = new SoftReference<String>(str); str = null; System.gc(); System.runFinalization(); System.out.println(s.get()); // print sdf String str = new String("sdf"); WeakReference<String> s = new WeakReference<String>(str); str = null; System.gc(); System.runFinalization(); System.out.println(s.get()); // print null;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
String str = new String("sdf"); ReferenceQueue<String> q = new ReferenceQueue<>(); PhantomReference<String> s = new PhantomReference<String>(str, q); str = null; System.out.println(s.get()); // print null; System.gc(); System.runFinalization(); System.out.println(q.poll() == s); // print true;