读书笔记_java编程思想

编程思想

2.一切都是对象

2.1用引用操作对象

在java中一切都被看做对象,但实际操作对象的是对象的引用,引用于对象的关系就像电视遥控与电视,声明一个引用而不指定对象,也是可以的,但是运行会报空指针,相当于买了有一个遥控器,却没有电视.

2.2对象的存储地

  1. 寄存器
    寄存器位于cpu内部速度最快但容量很小,所以java中根据需求分配寄存器.无法显式指定操作寄存器或向寄存器中存储对象,我们甚至无法感受到寄存器存在的痕迹

  2. 栈位于RAM中,速度仅次于寄存器,但创建程序时,编译器必须知道存储在栈中的所有项的确切生命周期,这一为了效率而产生的约束限制了栈中不能存放对象,只能存放对象的引用,[1]

  3. 堆也位于RAM中,存放了java中的所有对象,好处是编译器不需要所有项的确切生命周期,坏处是因为不知道确切的生命周期,堆中的存储和垃圾回收需要比栈中更多的时间.有利就有弊.java将这两种结构与对象的数据结合,打造出合适的jvm内存管理.
  4. 常量池
    存储不会改变的常量.
  • 特例:基本类型
    对于一些很小的,简单但是常用的变量,单独为他们在堆中创建一个对象,似乎效率不高.对于这些类型,java采用与c,c++同样的办法:创建一个不是引用的变量,这些变量直接存储值,并且置于栈中,而不是使用new来创建对象,因此更加高效.这些变量被称作基本类型变量.
  • 数组
    创建一个数组对象时,实际上就是创建了一个引用数组,并且所有引用都被初始化为一个特定值:null

2.5方法

在java中,方法是二等公民,不能单独存在,每个方法都必须依赖于类.要声明方法,必须先声明一个类来承载这个方法[2].
普通方法依赖于对象,必须先创建对象才能使用方法.
静态方法依赖于类,使用类本身就可以调用方法,不必须创建对象.

javadoc

3操作符

暂略

4控制执行流程

暂略

5初始化与垃圾回收

5.4 this关键字

一个类可以实例化多个对象,每个对象都可以调用类中的方法,那方法如何知道调用自己的是类中的哪个类呢,实际上,对象调用方法时,会将自己隐式传入方法中,想在方法中使用这个对象的话,this就可以出场了.也就是说,this就代表调用方法的对象.
摘抄

5.5 清理

[3]

5.6变量初始化

java的原则是:所有的变量在使用前(对象实例化)都应该得到恰当的初始化,所以所有变量在声明的时候就有一个默认值,基础类型变量默认值是0,false等.别的变量类型为null.
静态变量只会在类装载时被初始化一次,他是属于类的,只存在一份.假设static变量时一个随机值,多次创建类的对象不会获得不同的static变量.

5.7初始化顺序

成员变量将在方法之前被赋值完毕.(避免方法中使用变量时,变量未赋值完成,引起错误)
1.静态变量
2.静态代码块
2.普通成员变量
3.普通代码块
3.构造方法(隐式static)
4.普通方法
??静态方法啥时候加载,为什么用不了非静态成员变量
访问静态域或静态方法会导致类的加载,类的加载会加载所有static修饰的东西,包括域和方法.
初始化会引起上述顺序加载

5.8可变参数

5.9枚举

总结

在C++中,大量编程错误都源于不正确不完整的初始化,java中为了避免重蹈覆辙,使用了构造器这种保障结构.
实例化一个对象前,构造器中及构造器之前(变量赋值)来保证初始化完整.

7复用类

7.1组合

7.2继承

子类继承父类后,不只是将父类的属性和方法单纯复制到子类中.当创建一个子类对象时,该对象中包含了一个父类对象.这个父类对象和调用父类构造器获得的父类对象是一样的.区别仅仅是后者来自于外部,前者被包装在子类对象内部.
要达到上述效果,需要调用java提供给我们的保证对象初始化成功的结构---构造器.也就是说,子类构造器中会隐式调用父类构造器.如果父类没有空参构造器,需要在子类构造器第一行调用父类构造器,否则编译不会通过.
子类可以在自己的类中对父类方法进行重载,或者直接重写覆盖.

7.3代理

7.6protected

允许来自其他包的继承包内父类的子类访问父类的protected域,起到保护包的作用.不继承,不能访问.

7.7向上转型

子类在方法层面是父类的超集,子类中必定含有父类的所有方法,所以java允许隐式的向上转型.因为父类能调用的方法,子类肯定可以调用.
对于域来说,父类的private域或者friendly域,显式访问会报错,但子类向上转型后访问会编译通过并被初始化为null.

7.8final

static final修饰变量可以保证变量在类中只有一份且不变.
p147有加载顺序,很重要

  • final基本类型变量
    变量值不许改变
  • final引用类型变量
    引用不允许被重新指向其他对象,但对象本身可以改变,包括数组,数组也是对象
  • 空白final变量
    声明变量时不赋值,在构造方法中才对final变量赋值,通过对构造方法传参,这样更灵活.
    也就是说,final变量的确定是在对象初始化时才确定.这种方式局限性也在这里,不能用于static final修饰的变量.
  • final参数
    参数引用不允许被重新赋值
  • final方法
    所有private方法都隐式添加了final,因为他只对自己可见,也就不存在被子类重写的情况.
    在子类中声明一个方法声明和父类private方法声明一样的方法,不属于方法重写,只是声明了一个普通的子类方法.
  • final类
    不允许被继承,所有方法被隐式添加final

8多态

封装,继承,多态
子类可以重写父类的方法,并且子类引用可以自动向上转型为父类引用的这一特征,叫做继承.
在运行期间,父类的引用可以自动绑定为子类引用,以自动的调用具体子类的方法的这一过程,叫做动态.注意,多态只是针对普通方法的,对象的域以及静态方法,都不具有多态性.
子类调用顺序

9接口

需结合设计模式

  • 策略模式
  • 适配器模式

12异常

12.2java中的异常

  • 异常也是类
    java中的异常也是一个类对象,他也有一个默认的构造器,并且标准异常类都有一个参数为String类型的带参构造器,用于存储异常信息.
  • 抛出异常与方法返回的相似之处
    方法抛出异常与方法正常返回返回值有很多相似之处,比如:
    1.他们都可以中断方法继续执行
    2.正常返回会返回一个引用,抛出异常同样也会抛出一个异常的对象引用
  • 不同之处:
    处理返回对象的"目的地",方法返回值交给栈中的上一层调用方法,异常则交给适当的异常处理程序,具体要看谁有能力处理这个异常,一个异常可能会跨越许多方法调用栈才能找到他的处理程序.

12.3捕获异常

异常会被第一个可以处理他的catch语句捕获,并且捕获后就结束,也就是说,多个并列的catch语句并不会像swtich语句那样被捕获多次.但是一个异常被捕获后处理完也可以继续抛出

12.5声明你的异常

在方法声明上使用throws关键字来向上一层方法声明你的异常,如果上一层方法有能力处理,就会处理这些异常,没有的话,他们应该继续向上声明异常.

12.6栈轨迹

通过调用e.printStackTrace来打印异常信息,信息可以通过getStackTrace来直接访问,该方法将返回一个数组.
数组中元素是栈轨迹,每个元素表示栈中的一帧,索引为0的元素是栈顶元素,也就是最后一个方法调用(抛出异常之处),最后一个元素也就是栈底元素是调用的第一个方法.


  1. 这里不太明白,需要阅读更深层jvm书籍 ↩︎

  2. 情况在jdk8中似乎有所改变 ↩︎

  3. 暂时略过,但很重要 ↩︎

posted @ 2019-07-05 23:32  孔令翰  阅读(152)  评论(0编辑  收藏  举报