Java 再学习 模糊的知识 (四)

接口与内部类

1. 有关接口的一些知识点:
  • 接口不是类,不能用 new 运算符实例化一个接口。虽然不能构造接口的对象,但能够声明接口的变量,该变量必须引用实现了接口的类对象。
  • 可以使用 instanceof 检查一个对象是否实现了某个特定的接口。
  • 接口中不能包含实例域或静态方法,但却可以包含常量。
  • 接口中的方法都自动地被设置为 public ,接口中的域则被自动设置为 public static final 。
2. 有关对象克隆的一些知识点:
  • 当拷贝一个变量时,原始变量与拷贝变量引用同一个对象,这就是说,若该对象可变则对拷贝变量的修改会影响原始变量。
  • 若对象域均为数值、基本类型或不可变的子对象则进行浅拷贝,二者修改不会相互影响;但若是对象域中存在可变对象则进行浅拷贝后,对二者的修改会相互影响,此时为了得到互不影响但是状态在此刻相同的两个对象应该使用深拷贝
public static void cloneAndCopyTest() {
	//基本类型
	//a= 2 b= 2
	//a= 2 b= 3
	int a = 2;
	int b = a;
	System.out.println("a= "+a+" b= "+b);
	b = 3;
	System.out.println("a= "+a+" b= "+b);
	//不可变对象
	//s1= Good! s2= Good!
	//s1= Good! s2= Study
	String s1 = "Good!";
	String s2 = s1;
	System.out.println("s1= "+s1+" s2= "+s2);
	s2 = "Study";
	System.out.println("s1= "+s1+" s2= "+s2);
	//可变对象
	//d1= Fri Jan 02 00:00:00 CST 3920 d2= Fri Jan 02 00:00:00 CST 3920
	//d1= Thu Sep 02 00:00:00 CST 3920 d2= Thu Sep 02 00:00:00 CST 3920
	Date d1 = new Date(2020, 0, 2);
	Date d2 = d1;
	System.out.println("d1= "+d1+" d2= "+d2);
	d2.setMonth(8);
	System.out.println("d1= "+d1+" d2= "+d2);
	//对可变对象应该使用深拷贝
	//d1= Thu Sep 02 00:00:00 CST 3920 d3= Fri Jan 02 00:00:00 CST 3920
	Date d3 = (Date) d1.clone();
	d3.setMonth(0);
	System.out.println("d1= "+d1+" d3= "+d3);
}
  • 对于每个类,都需要做出下列判断:
    1)默认的 clone 方法是否满足要求。
    2)默认的 clone 方法是否能够通过调用可变子对象的 clone 得到修补。
    3)是否不应该使用 clone。
    实际上,选项3是默认的。如果要选择1或2,类必须:
    1)实现 Cloneable 接口。
    2)使用 public 访问修饰符重新定义 clone 方法。
3. 使用内部类的主要原因:
  • 内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据。
  • 内部类可以对同一个包中的其他类隐藏起来。
  • 当想要定义一个回调函数且不想编写大量代码时,使用匿名(anonymous)内部类比较
    便捷。
4. 可以在一个方法中定义局部类。局部类不能用 public 或 private 访问说明符进行声明。它的作用域被限定在声明这个局部。
5. 局部类的优点:
  • 对外部世界可以完全地隐藏起来。
  • 不仅能够访问包含它们的外部类,还可以访问局部变量。不过,那些局部变量必须被声明为 final 。
6. final 关键字可以应用于局部变量、实例变量和静态变量。在所有这些情况下,它们的含义都是:在创建这个变量之后,只能够为之赋值一次。此后,再也不能修改它的值了,这就是 final 。定义时没有初始化的 final 变量通常被称为空 final 变量。
7. 有的时候局部类的 final 限制使得程序编写不太方便,补救的方法是使用一个长度为1的数组(数组变量仍然被声明为 final,但是这仅仅表示不可以让它引用另外一个数组。数组中的数据元素可以自由地更改。)
8. “双括号初始化”。假设你想构造一个数组列表,并将它传递到一个方法,传递后便不再使用这个数组列表则最好让它作为一个匿名列表。
//双括号初始化 [Tom, Tim]
public static void doubleBracket() {
	//外层大括号建立了ArrayList的匿名子类,内层大括号则是一个对象构造块
	System.out.println(new ArrayList<String>() {{add("Tom");add("Tim");}});
}
9. 静态内部类:
  • 有时候,使用内部类只是为了把一个类隐藏在另外一个类的内部,并不需要内部类引用外围类对象。为此,可以将内部类声明为 static ,以便取消产生的引用。
  • 当然,只有内部类可以声明为static。静态内部类的对象除了没有对生成它的外围类对象的引用特权外,与其他所有内部类完全一样。
  • 声明在接口中的内部类自动成为 static 和 public 类。

学习整理自《Java 核心技术 卷一 基础知识》

发布了57 篇原创文章 · 获赞 25 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章