《Java核心卷I》笔记:继承

本博客只用于个人查漏补缺

类、超类、子类

子类构造器

  • 使用super关键字调用构造器的语句必须是子类构造器的第一条语句
  • 子类的构造器没有显示的调用超类的构造器,将自动的调用超类的无参构造
    如果超类没有无参构造,并且在子列的构造器中没有显式的嗲用超类的其他构造器,Java编译器会报错
  • 动态绑定:对象变量在运行时自动的选择适当的方法
  • 静态绑定:如果是private,static,final方法,编译器将准确的知道该调用那个方法,不依赖于隐式参数的类型

继承层次

  • 继承层次:一个公共超类派生出来的所有类的集合
  • 继承链:继承层次中,某个特定的类到其祖先的路径

理解方法调用

  • 重载解析:编译器确定方法调用中提供的参数类型,在所有方法名为 f 的方法中搜索一个与所提供的参数类型完全匹配的方法,就选择这个方法
  • 虚拟机预先为每一个类计算了一个方法表,其中列出了所有方法的签名和要调用的实际方法,这样在查找时,虚拟机只要查这个表就可以了
  • 运行时,调用 e.getSalary() 的解析过程为:
    虚拟机获取 e 的实际类型的方法表,根据具体对象
    接下来,虚拟机查找定义了 getSalary() 签名的类
    最后,虚拟机调用这个方法
  • 注意:覆盖一个方法时,子类方法不能低于超类方法的可先性,
    例如:超类方法为public,子类方法就必须为public

阻止继承:final类和方法

  • 不允许被扩展的类成为final类
  • 不允许被覆盖的方法被声明为final
  • 如果一个类声明为final,那么其中的方法自动成为final,不包括字段
  • 方法或类声明为final的原因:确保不会在子类中被改变语义
    如:Calendar类中getTime和setTime,这表明Calendar类负责Date类与日历状态的转换,而不允许子类来添乱;String类为final类,意味着不允许任何人定义String的子类
  • 内联(inlining) 如果一个方法没有被覆盖并且很短,编译器会对它进行优化处理
    如:e.getName() 将被替换成访问字段 e.name
  • 如果方法很简短,被频繁调用并且没被覆盖,那么即时编译器会将该方法进行内联处理
    如果虚拟机加载了另一个类,而这个子类覆盖了一个内联方法,优化器将取消这个方法的内联。

抽象类

  • 即使不包含抽象方法,也可以将类声明为抽象类
  • 抽象类不能实例化
  • 可以定义一个抽象类的对象变量,但这个变量只能引用非抽象子类的对象(类似多态)

访问控制修饰符小结

  • private:仅对本类可见
  • 默认:对本包可见
  • protected:对本包和所有子类可见
  • public:对外部完全可见 Object:所有类的超类 Object类型的变量
  • Java中,只有基本类型:数值,字符,布尔, 不是对。所有的数组类型,不管是对象数组还是基本类型的数组都扩展了Object类
    ### equals方法
  • 使用Object.equals(a, b)可以防止两个参数都为null的情况,如果都为null,返回true,如果一个为null,返回false,如果都不为null 调用 a.equals(b)

java.util.Arrays

  • static boolean equals(xxx[] a, xxx[] b) 如果两个数组长度相同,并且对应位置元素相同,返回true,或者都为null也返回true

hashCode方法

  • 由于hashCode()方法定义在Object类中,每个对象都有一个默认的散列码,其值由对象的存储地址得出
  • equals 与 hashCode的定义必须相容:如果 x.equals(y) 返回true,那么 x.hashCode() 就必须等于 y.hashCode()
  • Object.hashCode(a) 如果a 为null,返回0,否则返回a.hashCode()
  • Object.hash(x1, x2, x3)是对各个参数调用Object.hashCode,并组合这些散列值
  • Arrays.hashCode()方法计算一个散列码,散列码由数组元素的散列码组成

泛型数组列表

  • Java允许运行时确定数组大小,C/C++中必须在编译时就确定整个数组的大小
  • ArrayList 如果已经知道或者能够估计数组可能存储的元素数量,就可以在填充数组之前调用ensureCapacity(定义的长度)方法,此方法将调用分配一个包含指定对象数量的内部数组,在加入新元素时只要不超过这个数量就不用多次重新分配空间
    或者将初始容量创给ArrayList构造器
    ArrayList<Integer> a = new ArrayList<>(100);
  • trimToSize()将存储块的大小调整为保存当前元素数量所需要的空间

对象包装器与自动装箱

  • 拆箱和装箱是编译器要做的工作,不是虚拟机,编译器在生成类的字节码时会插入必要的方法调用,虚拟机只是执行这些字节码

参数数量可变的方法

  • Object… 参数类型 与 Object[] 完全一样
  • 也就是说,允许将数组作为最后一个参数传递给有可变参数的方法
  • 如果一个已有方法的最后一个参数是数组,可以吧它重新定义为有可变参数的方法,而不会破坏任何已有的代码

反射

Class类

Java运行时系统会为所有对象维护一个运行时类型标识,这个信息会跟踪每个对象所属的类
可以使用一个特殊的Java类访问这些信息,保存这些信息的类名为Class

  • 获得一个Class类型的实例的方法:
    • Object类中的getClass()方法会返回一个Class类型的实例
    • 使用静态方法 forName()获得类名对应的Class对象
    • T是任意的Java类型或Java关键字,T.Class 将代表匹配的类对象
  • 注意:一个Class对象实际上表示的是一个类型,可能是类,也可能不是类,如 int 不是类,但 int.class 是一个Class类型的对象
  • 虚拟机为每一个类型管理一个唯一的Class对象,可以利用 == 运算符实现两个类对象的比较
    如:if(e.getClass() == Employ.class)
  • Class类型的对象嗲用 getConstructor 方法将得到一个Constructor类型的对象,然后使用 newInstance 方法构造一个实例
    如果这个类没有无参构造,那么将会抛出一个异常
  • Class类中的 getFields、getMethods和getConstructors方法将分别返回类支持的公共字段、方法和构造器的数组,包括超类的成员
  • 而 getDeclareFields …只能返回类中声明的全部字段….不包括超类的成员
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇