Thinking in Java 笔记

Thinking in Java 笔记

1.oop:Object Oriented Programming 面向对象的程序设计

2.每个对象在内存中都有唯一的地址

3.类描述了具有相同特性(属性)和行为(方法)的对象集合

4.程序员的目的,创建(或者最好实在现有代码库(Github)中寻找)能够提供理想的服务来解决问题的一系列对象

5.如何分析一个对象:例如,加入你正在创建一个薄记系统,那么可以想象,系统应该具有某些包括了预定义的薄记输入屏幕的对象,一个执行薄记计算的对象集合,以及一个处理在不同的打印机上打印支票和开发票的对象。也许上述对象中的某些已经存在了,但是对于那些并不存在的对象,他们看起来像上面样子?他们能够提供那些服务?他们需要那些对象才能旅行他们的义务?

6.提高对象的高内聚性:例如,在检查打印模式的模块中,你可以这样设计对象,一个对象可以是所有可能的支票排版的目录,可以查询如何打印一张支票的信息;另一个对象可以是通用的打印接口,知道有关所有不同类型的打印机信息(可能是github有的接口了);第三个对象通过调用另外两个对象来完成打印任务。–就像这样,不仅允许通过购买获得对象那个,还可以创建能够在别处服用的新对象。

7.Java封装性的意义在于隐藏实现细节,隐藏的部分通常是程序内部脆弱的部分,很容易被粗心的不知情的程序员破坏,因此隐藏起来可以减少程序bug。

8.多态的好处:把一个对象不当做它所属的特定类型对待,而是当做是父类(基类),这样添加新的子类可以轻松拓展设计的能力,降低软件维护的代价。

9.对象(电视 new Tv())在堆上创建;对象的引用(遥控器 Tv tvController)在栈上创建;基本类型是直接将变量值存储在栈中

10.Java的容器(List,Map,Set):①不同容器提供了不同类型的接口和行为,某些容器提供的解决方案比其他容器灵活多了。②不同容器的某些操作有不同的效率。ArrayList和Linklist都是有相同的接口和外部行为的简单序列,但Arraylist随机访问元素是花费固定时间的操作,而Linklist随机取元素需要在列表移动,代价高,访问越尾的元素花费时间越长;而如果想在序列中间插入一个元素,Linklist开销比Arraylist小,因为Linklist只要改后一个元素的指定地址就能插入元素,而Arraylist要把插入位置后面的元素全部移项,花费高。我们可以一开始用Linklist构建程序,而在优化系统性能改用Arraylist。

11.泛型是为了解决向下转型(父类转子类)时转了错误的类型,而出现的运行时错误而设计的。

12.当一个对象存入容器的时候,他们会向上转型为Object类存入,但传出的时候,编译器是无法知道他传进来的时候是什么类型哦。(解决方法,加入泛型)

ArrayList<Shape> shapes = new ArrayList<Shape>();

13.对象的创建和生命周期(p13)–为什么选择Java?

14.必须由你创建所有对象(p22讨论 堆栈 堆 寄存器 等等概念)

15.BigInteger和BigDecimal用于处理高精度大数,牺牲速度换精度。

16.在花括号内定义的对象引用和对象,对象引用的作用于在花括号内,但对象会继续存在,需要通过垃圾回收期清理。

17.全局和静态的基本成员有初始值,局部变量可能是任意值,如果不赋值,有编译错。

18.Java参数的传递是值传递。

我们把对象传给方法里的形参,实际上我们相当于执行了copy()给新的引用,两个引用都指向了同一个地址,在方法中我们改变形参的值,实际上我们再次把形参指向新的地址,现在,这个地址发生的改变,不会影响到原来地址吧。如果你网上看到有人举了一个“引用传递”的例子,而且看起来“正确”,你可以从内存的角度,考虑一下为什么正确,正确了真的会影响到值传递这个事实吗?其实不然~

19.基本类型的初始值如int为0,boolean为false,而包装类型的初始值为null

20.有了基本类型为什么还要有包装类型呢?

我们知道Java是一个面相对象的编程语言,基本类型并不具有对象的性质,为了让基本类型也具有对象的特征,就出现了包装类型(如我们在使用集合类型Collection时就一定要使用包装类型而非基本类型),它相当于将基本类型“包装起来”,使得它具有了对象的性质,并且为其添加了属性和方法,丰富了基本类型的操作。

另外,当需要往ArrayList,HashMap中放东西时,像int,double这种基本类型是放不进去的,因为容器都是装object的,这是就需要这些基本类型的包装器类了。

21.静态方法其实与它的类无关。

22.static关键字,为了使被它修饰的事物,脱离于其任何对象实例存在,所以不需要创建对象就可以调用静态方法。

23."+"意味着''字符串连接'',如果必要,还有''字符串转换''

24.equals不适用与基本类型,因为是Object的方法,基本类型没有父类。

public void test4() {
        Integer a = new Integer(47);
        Integer b = new Integer(47);
        System.out.println(a == b);//地址不相等,false
        System.out.println(a.equals(b));//equals被重写了,值相等,true
    }

25.java不支持goto,但仍然是保留字。

26.父子初始化速度比较:父类静态代码块>子类静态代码块>父类构造方法>子类构造方法(构造器默认其实是静态方法)

27.区分重载:参数 顺序or数量or类型 的不同(顺序一般不用,会让代码难以维护)

28.返回当前对象的引用

Person walk(){
    return this;
}

28.垃圾回收器只会回收new分配的内存,而其他内存它不知道如何处理。java允许类中定义一个名为finalize()的方法,在垃圾回收准备释放对象占用的储存空间前,先调用finalize()方法,并在下次垃圾回收动作时,才真正回收对象占用的内存。

对象可能不被垃圾回收
垃圾回收并不等于"析构"("析构"是c++的概念)
垃圾回收至于内存有关

29.如果一直到程序执行结束,垃圾回收器都没有释放任何对象的储存空间,则随着程序的退出,那些资源也会全部交还给操作系统,因为垃圾回收本身也要开销,不使用,就不用支付这部分开销。

30.finalize()不是进行普通清理工作的合适场所

finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法。
finalize()与C++中的析构函数不是对应的。C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉),但Java中的finalize的调用具有不确定性
不建议用finalize方法完成“非内存资源”的清理工作,但建议用于:① 清理本地对象(通过JNI创建的对象);② 作为确保某些非内存资源(如Socket、文件等)释放的一个补充:在finalize方法中显式调用其他资源释放方法。其原因可见下文[finalize的问题]

31.无论是"垃圾回收"还是"终结"都不保证一定发生,如果Java虚拟机并未面临内存耗尽的情形,他是不会浪费时间去执行垃圾回收以回复内存的。

32.静态数据初始化

public class StaticInitialization {
    /**
     * 
     * @Title: 静态数据的初始化   
     * @Description: TODO(复杂的跳转初始化)       
     * @return: 
     * 结论1:按顺序初始化 static 变量/对象 -> 执行主(static)方法 
     * 结论2:用构造函数new一个对象时 -> 先初始化改对象所在类的 static 变量/对象 -> 再执行构造(staitc)方法
     * 结论3:static 变量/对象 只会初始化一次(首次生成这个类的对象时,或者首次访问属于那个类的静态数据成员时)
     */
    public static void main(String[] args) {
        System.out.println("Create new Cupboard() in main");//11
        new Cupboard();//12
        System.out.println("Creating new Cupboard() in main");//16
        new Cupboard();//17
        table.f2(1);//21
        cupboard.f3(1);//22
    }
    static Table table = new Table();//0
    static Cupboard cupboard = new Cupboard();//5
}
class Bowl{
    Bowl(int marker) {
        System.out.println("Bow("+marker+")");
    }
    void f1(int marker) {
        System.out.println("f1("+marker+")");
    }
}
class Table{
    static Bowl bowl1 = new Bowl(1);//1
    Table(){
        System.out.println("Table()");//3
        bowl2.f1(1);//4
    }
    void f2(int marker) {
        System.out.println("f2("+marker+")");
    }
    static Bowl bowl2 = new Bowl(2);//2
}
class Cupboard{
    Bowl bowl3 = new Bowl(3);//8,13,18
    static Bowl bowl4 = new Bowl(4);//6
    Cupboard() {
        System.out.println("Cupboard");//9,14,19
        bowl4.f1(2);//10,15,20
    }
    void f3(int marker) {
        System.out.println("f3("+marker+")");
    }
    static Bowl bowl5 = new Bowl(5);//7
}

33.构造器的出现,保证了正确的初始化和清理,有了完全的控制,也就安全了。

34.package关键字的出现,是为了让编译器知道我们跟其他包的位置差异,这样public/protect/private才能限制访问权限。

35.package语句必须是文件中的第一行非注释程序代码。(不一定要在line1哦)

36.当编译器遇到import语句时,会在CLASSPATH里面找import后面的包名,然后从已编译的文件中找出名称相符者。

37.如果你import的两个包邮同名的class,这就存在潜在的冲突,但只要你不写那些导致冲突的程序代码,就没有问题。

//比如Vector.class冲突了,编译器不知道你new Vector是创建那个,就得下面这样写。
java.util,Vector v = new java.util.Vector();

38.private,默认,protected,public

//private:同类
//默认:同类,同包
//protected:同类/子类/同包,注意的是,不同包的子类去访问这样写:super.protected_Attr;(用super)
//public:同类,同包,不同包(所有..)

39.代理模式,可以隐藏真实者代理者选择性提供真实者的方法,避免真实者的所有方法暴露给使用者。

40.在继承里,子类的构造方法,默认第一行调用super(),除非你手动调用super(…)(父类其它构造方法),因为编译器肯定要你先初始化父类的,无论什么形式。如果你父类没有默认的构造方法,而是重写了带参数的构造方法,子类构造方法必须显式调用super(…),否则编译时错误。

41判断是否需要使用继承:问一下自己是否需要 从新类向基类进行向上转型(子类变父类),如果必须向上转型,则继承是必须的;但如果不需要,则好好考虑使用组合(依赖注入)还是使用继承

42.final修饰词

//一个永不改变的编译时变量(必须是基本类型,减轻运行时负担)
//一个在运行时被初始化的值,而你不希望它被改变
//对于基本类型,final使数值恒定不变;而使用对象引用,final使引用恒定不变。(一旦引用被初始化执向一个对象,就无法再把它指向另一个对象。然而对象自身是可以被修改的,java并未提供使任何对象恒定不变的途径;数组,字符串都是对象!!)
//貌似,使引用成为final,没有使常量成为final用处大

43.定义为static,强调只有一份,定义为final,强调是常量。

44.空白final(final修饰的变量使用前必须初始化,空白final让初始化延迟且更加灵活,可以根据对象而有所不同)

class Test2 extends Day3{ 

    private final String name;

    public Test2(String name) {
        super(name);
        this.name = name;
    }

    public static void main(String[] args) {
        Test2 tt= new Test2("suguowen");
        System.out.println(tt.name);
        //tt.test1();
    }
    public void test1() {
        Day3 d = new Day3();
        /*System.out.println(super.private_Num);
        System.out.println(super.default_Num);*/
        System.out.println(super.protected_Num);
        System.out.println(super.public_Num);
    }
}

45.final修饰方法,把方法锁定,防止继承类修改它的定义;确保继承中使方法行为保持不变,并且不被覆盖。

46.所有private方法都隐式地指定了final,但因为private是隐式的,所以子类可以“覆盖”这个方法,但其实,子类不知道父类有这个方法,所以也就不存在覆盖一说

47.一个类的代码在初次使用时才会加载

48.多态:指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)。

  
//假设data和getData()父子类都有
Super sup = new Sub();
sup.data;//将会调用父类的data
sup.getData;//将会调用子类的getData
//假设data和getData()父子类都有
Super sup = new Sub();
sup.data;//将会调用父类的data
sup.getData;//将会调用子类的getData

49.初始化一个对象的时候,先初始化静态代码块,再初始化全局变量,再初始化构造函数。

50.抽象类无法创建对象。

51.在interface中没有任何方法被声明为public,但是他们自动就是public。

51.策略模式,ABC都继承于X,使用者调用方法时将对象参数(A,B,C)和普通参数传入s方法(s是父类X的抽象方法),在s方法中,重新调用参数对象(A,B,C)的s方法(跟代理者模式有点像),从而实现策略。跟代理模式有什么不同呢,代理模式注重把一个真实者的全部方法都给代理者代理(代理者其实调用耦合了真实者,调用真实者的方法),进而隐藏真实者的存在;策略模式注重策略,同一个方法来调用不同的实现,只有在使用的时候,才决定用哪个策略。(策略也是提前写的,废话哦)

52.适配器模式,接口A,BCD都是他的实现类,s方法需要对象参数A即可策略的调用BCD方法了;这时候出现了以E为父类的一系列超好用的GHI子类;我们希望s方法可以把GHI也纳入为策略(但s方法只接受接口A为参数),那怎么办呢?我们可以创建一个Adapter类来实现A接口,Adapter耦合E(E是GHI的父类哦),初始化Adapter的时候,传入E的子类,用工厂模式实例化E,然后Adapter实现A接口的方法,把方法里的实现换成E的实现(代理模式)。虽然看上去用到了很多模式,但其实是我这个例子写的复杂了,适配器模式的思想其实是,你在用A接口来做事件S,但突然你老板叫你用B来做事件S,这时候S和B没有任何关系,你需要一个适配器Adapter来实现A,并且把B注入进去;这样你的A就包含了B,你就可以用B来做事件S了。

53.接口的域默认是public

54.内部类的作用,允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性

55.内部类最出色的地方在于,每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的、可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。接口解决了部分多重继承的问题,而内部类有效的实现了多重继承。

56.理解什么时候使用多态,什么时候使用接口、抽象类、内部类。(p215)

第十一章

1.数组一旦生产能,其容量就不能改变 ;Collection和map添加更多元素的时候,自动调整尺寸。

2.数组和List都是排序好的容器。

3.如果要进行大量的随机访问,就是用ArrayList,如果经常从表中间插入或删除数据,则应该用LinkedList。

4.各种Queue以及栈的行为,由LinkedList提供支持。

5.HashMap设计用来快速访问;而TreeMap保持“键”始终处于排序的状态,所以没有HashMap快。LinkedHashMap保持元素的插入顺序但是也通过散列提供了快速访问的能力。

6.Set不接受重复元素。HashSet提供最快的查询速度,而TreeSet保持元素处于排序状态。LinkedHashSet以插入顺序保存元素。

7.Vector、Hashtable、Stack都过时了,不应该使用。

 

第十二章

1.当抛出异常时,将在堆上创建异常对象,当前执行路径被终止,异常处理机制接管程序,并用异常处理程序让

程序从错误状态恢复,让程序换一种方式运行或继续运行下去。

2.无论异常是否抛出,finally字句总是被执行。

 

第十三章

1.String对象不可变,String类中每一个看齐俩会修改String值的方法,实际上都是创建了一个全新的String对象。每当把String独享作为方法的参数时,都会复制一份引用,而该引用所指的对象其实一直待在单一的物理位置上,从未动过。

2.对于一个方法而言,参数是为该方法提供信息的,而不是想让该方法改变自己的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
写在前面的话 引言 1. 前提 2. Java的学习 3. 目标 4. 联机文档 5. 章节 6. 练习 7. 多媒体 8. 源代码 9. 编码样式 10. Java版本 11. 课程和培训 12. 错误 13. 封面设计 14. 致谢 第1章 对象入门 1.1 抽象的进步 1.2 对象的接口 1.3 实现方案的隐藏 1.4 方案的重复使用 1.5 继承:重新使用接口 1.5.1 改善基础类 1.5.2 等价和类似关系 1.6 多形对象的互换使用 1.6.1 动态绑定 1.6.2 抽象的基础类和接口 1.7 对象的创建和存在时间 1.7.1 集合与继承器 1.7.2 单根结构 1.7.3 集合库与方便使用集合 1.7.4 清除时的困境:由谁负责清除? 1.8 违例控制:解决错误 1.9 多线程 1.10 永久性 1.11 Java和因特网 1.11.1 什么是Web? 1.11.2 客户端编程 1.11.3 服务器端编程 1.11.4 一个独立的领域:应用程序 1.12 分析和设计 1.12.1 不要迷失 1.12.2 阶段0:拟出一个计划 1.12.3 阶段1:要制作什么? 1.12.4 阶段2:开始构建? 1.12.5 阶段3:正式创建 1.12.6 阶段4:校订 1.12.7 计划的回报 1.13 Java还是C++? 第2章 一切都是对象 2.1 用句柄操纵对象 2.2 必须创建所有对象 2.2.1 保存在什么地方 2.2.2 特殊情况:主类型 2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的作用域 2.4 新建数据类型:类 2.4.1 字段和方法 2.5 方法、自变量和返回值 2.5.1 自变量列表 2.6 构建Java程序 2.6.1 名字的可见性 2.6.2 使用其他组件 2.6.3 static关键字 2.7 我们的第一个Java程序 2.8 注释和嵌入文档 2.8.1 注释文档 2.8.2 具体语法 2.8.3 嵌入 2.8.4 @see:引用其他类 2.8.5 类文档标记 2.8.6 变量文档标记 2.8.7 方法文档标记 2.8.8 文档示例 2.9 编码样式 2.10 总结 2.11 练习 第3章 控制程序流程 3.1 使用Java运算符 3.1.1 优先级 3.1.2 赋值 3.1.3 算术运算符 3.1.4 自动递增和递减 3.1.5 关系运算符 3.1.6 逻辑运算符 3.1.7 按位运算符 3.1.8 移位运算符 3.1.9 三元if-else运算符 3.1.10 逗号运算符 3.1.11 字串运算符 3.1.12 运算符常规操作规则 3.1.13 造型运算符 3.1.14 Java没有“sizeof” 3.1.15 复习计算顺序 3.1.16 运算符总结 3.2 执行控制 3.2.1 真和假 3.2.3 反复 3.2.6 中断和继续 3.2.7 切换 3.3 总结 3.4 练习 第4章 初始化和清除 4.1 由构建器保证初始化 4.2 方法过载 4.2.1 区分过载方法 4.2.2 主类型的过载 4.2.3 返回值过载 4.2.4 默认构建器 4.2.5 this关键字 4.3 清除:收尾和垃圾收集 4.3.1 finalize()用途何在 4.3.2 必须执行清除 4.4 成员初始化 4.4.1 规定初始化 4.4.2 构建器初始化 4.5 数组初始化 4.5.1 多维数组 4.6 总结 4.7 练习 第5章 隐藏实施过程 5.1 包:库单元 5.1.1 创建独一无二的包名 5.1.2 自定义工具库 5.1.3 利用导入改变行为 5.1.4 包的停用 5.2 Java访问指示符 5.2.1 “友好的” 5.2.2 public:接口访问 5.2.3 private:不能接触 5.2.4 protected:“友好的一种” 5.3 接口与实现 5.4 类访问 5.5 总结 5.6 练习 第6章 类再生 6.1 合成的语法 6.2 继承的语法 6.2.1 初始化基础类 6.3 合成与继承的结合 6.3.1 确保正确的清除 6.3.2 名字的隐藏 6.4 到底选择合成还是继承 6.6 递增开发 6.7 上溯造型 6.7.1 何谓“上溯造型”? 6.8 final关键字 6.8.1 final数据 6.8.2 final方法 6.8.3 final类 6.8.4 final的注意事项 6.9 初始化和类装载 6.9.1 继承初始化 6.10 总结 6.11 练习 第7章 多形性 7.1 上溯造型 7.1.1 为什么要上溯造型 7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值