标签:
接口决定了实现该接口的类型的对象能发出什么消息。比如手机在初期就被设计成为可以[打电话]、[发短信]、[拍照],这些动作可以看做是接口,实现了这些接口就是一部手机。接口把这些必要的方法聚集起来,就能让实现接口的类型发出指定的消息。
将对象看作服务提供者,避免对象累赘,提高对象的内聚性,可重用性。
访问控制:将程序开发人员分为类创建者和客户端程序猿,只向客户端程序猿暴露必要的部分,因为有些属性和方法在类内部操作是必要的,但是客户端程序猿并不需要关心,不让其访问和操作对象内部脆弱的地方,可以减少bug,提高安全性,也可以让他们看出哪些东西对他们来说是重要的。其次,访问控制让接口的实现和调用分离,即使内部发生了翻天覆地的变化,也不会影响客户端程序的使用。
public:任何人可使用;private:类型内部可使用,外部无法访问;protected:类型内部可使用,与private相似,但是继承的类可以直接访问protected;无访问指定词:包访问权限,在同一个包内,可以看做是public,但是在不同类中却可以看做是private,无法访问无访问指定词的属性和方法;
1 package com.chenlei.study.thinkinginjava;
2 /**
3 * @author chenlei
4 * @date 2016年4月18日 下午10:55:16
5 * @version 1.0
6 * @description
7 */
8 public class AccessSpecifier {
9 String string = "default field from same package";
10 String print(){
11 return "default method from same package";
12 }
13 }
1 package com.chenlei.study.utils;
2 /**
3 * @author chenlei
4 * @date 2016年4月18日 下午10:56:47
5 * @version 1.0
6 * @description
7 */
8 public class AccessSpecifierOtherPackage {
9 String string = "default field from another package";
10 String print(){
11 return "default method from another package";
12 }
13 }
1 package com.chenlei.study.thinkinginjava;
2
3 import com.chenlei.study.utils.AccessSpecifierOtherPackage;
4
5 /**
6 * @author chenlei
7 * @date 2016年4月18日 下午10:59:41
8 * @version 1.0
9 * @description 访问限定词
10 */
11 public class AccessSpecifierEntry {
12
13 public static void main(String[] args) {
14 String stringSamePackage = new AccessSpecifier().string;
15 new AccessSpecifier().print();
16
17 String stringOtherPackage = new AccessSpecifierOtherPackage().string;//The field AccessSpecifierOtherPackage.string is not visible
18 new AccessSpecifierOtherPackage().print();//The method print() from the type AccessSpecifierOtherPackage is not visible
19 }
20 }
复用并不是一味地继承,这样可能导致过分复杂的设计,而是在合适的时候用不同的已有对象组合成一个新的对象。
拥有基类所有的属性和方法,但是想要扩展或改写某些方法时,不必创建新对象,可以继承基类并进行方法覆盖或扩展。这就意味着继承自基类的子类在接收到父类能够接手的消息时,能够做出响应,如果不覆盖父类的方法,子类将会做出和父类一样的响应,否则做出自己特定响应。也就是说子类能够对发送给父类的所有消息作出相应。
当基类完全继承和覆盖父类方法并不添加其他属性和方法,也不实现其他接口时,可以说子类是一个基类完全的替代,子类就是一个基类类型;当子类不满足前面的条件时,子类和基类就不完全一样了,子类就不是一个纯粹的基类类型。
1 package com.chenlei.study.thinkinginjava;
2 /**
3 * @author chenlei
4 * @date 2016年4月18日 下午11:27:46
5 * @version 1.0
6 * @description 转型
7 */
8 public class Cast {
9 public static void main(String[] args) {
10 Rectangle rectangle = new Rectangle();
11 Circle circle = new Circle();
12 Shape shape = new Shape();
13
14 shape = circle;
15 circle.computeArea();
16 shape.computeArea();
17
18 Circle circle2 = (Circle) shape;//转换成功,因为shape指向circle的地址,是一个circle的实例
19
20 shape = new Shape();
21 circle = (Circle) shape;//com.chenlei.study.thinkinginjava.Shape cannot be cast to com.chenlei.study.thinkinginjava.Circle
22 circle.computeArea();
23 shape.computeArea();
24
25 shape = rectangle;
26 rectangle.computeArea();
27 shape.computeArea();
28
29 shape = new Shape();
30 rectangle = (Rectangle) shape;//com.chenlei.study.thinkinginjava.Shape cannot be cast to com.chenlei.study.thinkinginjava.Rectangle
31 rectangle.computeArea();
32 shape.computeArea();
33 }
34 }
35
36 class Shape{
37 protected Double area = 1d;
38 public void computeArea(){
39 System.out.println("shape");
40 System.out.println(area);
41 };
42 }
43
44 class Circle extends Shape{
45 @Override
46 public void computeArea(){
47 System.out.println("circle");
48 super.computeArea();
49 }
50 }
51
52 class Rectangle extends Shape{
53 private Double width = 1d;
54 private Double height = 2d;
55 private Double perimeter;
56
57 @Override
58 public void computeArea() {
59 System.out.println("rectangle");
60 area = width * height;
61 System.out.println(area);
62 }
63
64 public void computePerimeter(){
65 System.out.println("rectangle");
66 perimeter = 2 * (width + height);
67 System.out.println(perimeter);
68 }
69 }
子类可以自动转化成一个父类,因为父类的所有消息,子类都可以响应;一个子类却不能强制转化为父类,因为子类有很多,无法具体到某一个特定的子类(除非父类引用的子类的一个实例)。很显然子类之间也无法相互强制转换,在编译期就会出错。所以向上转型是安全的,向下转型是不安全的,因为一个圆一定是一个形状,但是一个形状却不能具体到到底是一个圆还是一个三角形。
1 package com.chenlei.study.thinkinginjava; 2 /** 3 * @author chenlei 4 * @date 2016年4月19日 下午10:45:56 5 * @version 1.0 6 * @description 多态 7 */ 8 public class Polymorphism { 9 10 public static void main(String[] args) { 11 Bird bird = new Bird(); 12 Chicken chicken = new Chicken(); 13 Goose goose = new Goose(); 14 15 move(bird);//----bird move---- 16 move(chicken);//----chicken walk---- 17 move(goose);//----goose fly---- 18 } 19 20 public static void move(Bird bird){ 21 bird.move(); 22 } 23 24 } 25 26 class Bird{ 27 public void move(){ 28 System.out.println("----bird move----"); 29 } 30 } 31 32 class Chicken extends Bird{ 33 @Override 34 public void move() { 35 System.out.println("----chicken walk----"); 36 } 37 } 38 class Goose extends Bird{ 39 @Override 40 public void move() { 41 System.out.println("----goose fly----"); 42 } 43 }
所有对象最终都继承自Object类。单根继承保证所有对象都具备某些功能,比如Object的hashCode和equals方法等,这让一些更高级别的操作更加便利,比如GC和异常处理。
1.Java里常用的容器,后面必须专门花时间总结,并且从源码角度分析与实现。
2.范型:在JSE5之前,容器里只能存储Object,这就使得从容器中取回对象时需要进行不安全的向下转型,JSE5引入范型(一对尖括号,中间是类型 List<String> list = new ArrayList<String>(); ),这就使得取回元素时就像放入时一样,不需要再转型。
对象的存储位置可以是堆栈或堆。前者需要在程序编写时确定对象的存储空间、生命周期和类型,虽然在某种情况下这种控制方法很有效,但是却牺牲了灵活性,甚至因为程序未及时销毁对象导致内存泄漏;后者的创建和销毁是动态管理的,只有在程序运行需要的时候才能确定对象的存储空间、生命周期和类型,Java中采用的后者,创建对象时需要使用new关键字构建动态对象,Java专门的垃圾回收机制自动释放对象占用的内存,来避免暗藏的内存泄漏问题,可以不显式地在代码中调用方法释放内存,这些都是基于单根继承和对象在堆中管理这两个特性来实现的。
我觉得异常处理主要有两点作用:一是捕获到异常后作出报告、捕获并对异常情况作特殊处理,避免程序终止;二是便于完善代码,使程序更加健壮。
多线程、共享资源锁
[Thinking in Java]Nothing but Java
标签:
原文地址:http://www.cnblogs.com/Vabshroo/p/tkij-ch1.html