• 数据类型
    • 包装类型
    • 缓存池
  • String
    • 概览
    • 不可变的好处
    • String,StringBuffer and String Builder
    • String.intern()
  • 运算
    • 参数传递
    • float 与 double
    • 隐式类型转换
    • Switch
  • 继承
    • 访问权限
    • 抽象类与接口
    • super
    • 重写与重载
  • Object同样方法
    • 概览
    • equals()
    • hashCode()
    • toString()
    • clone()
  • 关键字
    • final
    • static
  • 反射
  • 异常
  • 泛型
  • 注解
  • 特性
    • Java各版本的新特性
    • Java 与 C++ 的区别
    • JRE or JDK

String

String 被声明为 final,因此它不可被继承
内部使用 char 数组存储数据,该数组被声明为final,这意味着 value 数组初始化之后及不能再引用其他数组。并且 String 内部没有改变 value 数组的方法,因此可以保证String不可变

不可变的好处
  1. 可以缓存 hash 值

因为 String 的 hash 值经常被使用,例如 String 用作 HashMap 的 Key。不可变的特性可以使得 hash 值也不可变,因此只需要进行一次计算

  1. String Pool 的需要

如果一个 String 对象已经被创建过了,那么就会从 String Pool 中取得引用。只有 String 是不可变得,才可能使用 String Pool。

  1. 安全性

String 经常作为参数,String 不可变性可以保证参数不可变。

  1. 线程安全

String 不可变性天生具备线程安全,可以在多个线程中安全的使用。

String , StringBuffer , StringBuilder

1. 可变性
  • String 不可变
  • StringBuffer , StringBuilder 可变

    2. 线程安全
  • String 不可变,因此是线程安全的

  • StringBuilder 不是线程安全的
  • StringBuffer 是线程安全的,内部使用 synchronized 进行同步

    String.intern()

    使用 String.intern() 可以保证相同内容的字符串变量引用同一的内存对象

参数传递

Java的参数是以值传递的形式传入方法中,而不是引用传递


抽象类 和 接口

比较
  • 从设计层面上看,抽象类提供了一种 IS-A 关系,那么久必须满足里氏替换原则,即子类对象必须能够替换掉所有父类对象。而接口更像一种 LIKE-A 关系,它只是提供一种实现契约,并不要求接口和实现接口的类具有 IS-A 关系
  • 从使用上来看,一个类可以实现多个接口牡丹石不能继承多个抽象类
  • 接口的字段只能是 static 和 final 类型的,而抽象类的字段没有这种限制
  • 接口的成员只能是 public,而抽象类的成员可以有多种访问权限

    使用选择

    使用接口

  • 需要让不相关的类都实现一个方法

  • 需要使用多重继承

使用抽象类

  • 需要在几个相关的类中共享代码
  • 需要能控制继承累的成员的访问权限,而不是都为 Public
  • 需要继承非静态和非敞亮的自读那

在很多情况下,接口优于抽象类,因为接口没有抽象类严格的类层次结构要求,可以灵活地为一个类添加行为。从 Java 8 开始,接口也可以有默认的访问实现,使得修改接口的成本也变得很低

super

  • 访问父类的构造函数:可以使用 super() 函数访问父类的构造函数,从而委托父类完成一些初始化的工作
  • 方位父类的成员:如果子类重写了父类中的某个方法的实现,可以通过使用 super 关键字类引用父类的方法实现

    重写

    存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法
    为了满足里氏替换原则,重写有以下两个限制:

  • 子类方法的访问权限必须大于等于父类方法

  • 子类方法的返回类型必须是父类方法返回类型或者为其子类型

使用 @override 注解,可以让编译器帮忙检查是否满足上面的两个限制条件

重载

存在于同一个类中,值一个方法与已经存在的方法名称上相同,但是参数类型、个数、顺序至少有一个不同
应该注意的是,返回值不同,其他都相同不算是重载


Object

equals()
  1. 等价条件

()自反性
()对称性
()传递性
()一致性
()与null的比较(除了 null),都是为false

  1. equals() 与 ==
  • 对于基本类型, == 判断两个值是否相等,基本类型没有 equals() 方法
  • 对于引用类型,== 判断两个变量是否引用同一个对象,而 equals() 判断引用的对象是都等价
  1. 实现
    hashCode()
    hashCode()返回散列值,而 equals() 是用俩判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价
    在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象散列值也相等
    clone()
    应该注意的是,clone() 方法并不是 Cloneable接口的方法,而是Object的一个 projected方法。Cloneable 接口只是规定,如果一个列没有实现 Cloneable接口,又调用了 clone() 方法,就会抛出 CloneNodeSupportedException.
  • 浅拷贝

拷贝对象的和原始对象的引用类型引用同一个对象

  • 深拷贝

拷贝对象和原始对象的引用类型引用不同对象


关键字

final
  1. 数据

声明数据为常量,可以是编译时常量,也可以是在运行时被初始化后不能被改变的常量

  • 对于基本类型,final使数值不变
  • 对于引用类型,final使引用不变,也就不能引用其他对象,但是被引用的对象本身是可以修改的
  1. 方法

声明方法不能被子类重写
private 方法隐式地被指定为final,如果子类中定义的方法与基类中的一个 private方法签名相同,此时子类的方法不是重写基类方法,而是在子类中定义了一个新的方法

声明类不允许被继承

static
  1. 静态变量
  • 静态变量:又称类变量,也就是说着这个变量术语类的,类所有的实例都共享静态变量,可以直接通过类名来访问它;静态变量在内存中只存一份
  • 实例变量:每创建一个实例就会产生一个实例变量,并与实例同生共死
  1. 静态方法

静态方法在类加载的时候就存在,它不依赖与任何实例,所以静态方法必须有时限,也就是说它不能是抽象方法(abstract)
只能访问所属类的静态字段和静态方法,方法中不能有 this 和 super 关键字

  1. 静态语句块

静态语句块在类初始化时运行一次

  1. 静态内部类

非静态内部类依赖于外部类的实例,而静态内部类不需要

  1. 静态导包
  2. 初始化顺序

静态变量和静态语句块由于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序。最后才是构造函数的初始化
存在基础的情况下,初始化顺序为:

  • 父类(静态变量、静态语句块)
  • 子类(静态变量、静态语句块)
  • 父类(实例变量、普通语句块)
  • 父类(构造函数)
  • 子类(实例变量、普通语句块)
  • 子类(构造函数)

反射

每个类都有一个Class对象,包含了与类相关的信息。当编译一个新类时,就会产生一个同名的 .class 文件,该文件内容保存着 Class 对象
类加载相当于 Class对象的加载。类在第一次使用时才动态加载到 JVM 中,可以使用 Class.forName(“com.myslq.jdbc.Driver”) 这种方式类控制类的加载,刚方法返回一个 Class对象

反射可以提供运行时的类的信息,并且这个类可以在运行时才加载进来,甚至在编译时该类的 .class 不存在也可以加载进来

Class 和 java.lang.reflect 一起对反射提供了支持。java.lang.reflect 类库中包含以下三个类:

  • Filed:可以使用 get() 和 set() 方法读取和修改 filed 对象关联的字段
  • Method: 可以使用 invoke() 方法调用与Method对象关联的方法
  • Constructor: 可以用 Constructor 创建新的对象