java.lang.String

特性

  • 不可变
  • 两种根据字面量构建字符串的方法
    • String str = "foo"; 直接指向字符串常量池中的 "foo",至多创建一个对象(常量池中的字符串)
    • String str = new String("foo"); 每个不同的字符串都会在“字符串常量池”中创建对象,也就是至多创建两个对象(String 对象 + 常量池中的字符串)
  • String.intern() 方法
    • 字符串字面量会保存在字符串常量池中
    • new String(...) 无论如何会在堆里创建对象
    • 其他类(例如 StringBuilderInteger)的 toString 方法,实际调用的是 new String(...)
    • String.intern() 方法可以手动把一个字符串加入常量池
  • String.split() 方法
    • 返回类型是 String[]
    • 按照正则表达式拆分
    • 可选的第二个参数 "abcba".split("b", 1)
      • 如果是正数,那么至多切成这么多段([abcba]
      • 如果是 ,那么尽量多切,并且删除最后的那些空段
      • 如果是任何负数,那么尽量多切,并且不删除最后的空段
  • 还可以用 Pattern 类 + Matcher 类进行拆分
    • static Pattern pattern = Pattern.compile("some_regex")
    • Matcher matcher = pattern.matcher(str)
    • 必须先调用 matcher.matches() 进行匹配
    • System.out.println(matcher.group(1)),从 开始编号

编码

  • 两种编码:latin-1(一个字节)或者 utf-16(2 或 4 个字节),由 coder 属性决定,用 byte 数组存储
  • charAt 返回 char(两个字节)
  • codePointAt 返回 int,表示那个字符(若干字节),可以用 Character.toString(int codePoint) 转换为字符串

面向对象

Object 类的方法

  • 对象比较
    • hashCode()
      • native 函数,实现取决于 JVM 实现
      • 如果两个对象通过 equals 方法比较为 true,那么 hashCode() 应该相等
      • 但是如果为 false不要求 hashCode 一定不同
    • equals(Object obj):默认实现为 return (this == obj); 即比较地址
  • 对象拷贝
    • clone():默认实现为浅拷贝,但要求必须实现接口 Cloneable 才行
  • 对象转字符串
    • toString():默认实现由类名加上 hashCode() 组成
  • 多线程调度
    • wait(long timeout)
      • native 函数
      • 让当前线程等待被 notify 或者 interrupt(Java 中断机制)
    • wait(long timeout, int nanos):额外指定微秒数,更加精确
    • notify()native 函数,唤醒单个正在 wait 同一个对象的线程
    • notifyAll()native 函数,唤醒所有正在 wait 同一个对象的线程
    • getClass()native 函数,获取当前对象的运行时 Class 对象,用于反射相关
    • finalize():从 Java 9 开始已弃用

访问权限

  • 方法
    • public 方法:可以被任何类访问
    • private 方法:只能被当前类访问
    • protect 方法:可以被当前包中的任何类,或者其他包中自己的子类访问
    • default 方法(默认):只能被当前包中的任何类访问

构造方法

  • 不能是 finalabstractstaticsynchronized
  • 拷贝对象
    • 三种方法:构造函数,对应字段赋值,Object.clone 方法
    • Object.clone 方法
      • 默认实现是 native 函数,进行浅拷贝(即引用类型的字段的引用被复制)
      • 要想使用,必须实现 Cloneable 接口,Object 类没有实现 Cloneable 接口
  • 初始化块
    • 初始化块被 Java 编译器放在构造方法的开头执行
    • 执行顺序:父类静态初始化块 子类静态初始化块 进入 main 方法 父类构造方法 子类初始化块 子类构造方法

抽象类与接口

  • 抽象类可以有抽象方法和普通方法
    • 抽象方法不能是 static
    • 抽象方法在子类中必须实现
    • 抽象类可以继承抽象类,并且继承它的普通类仍然需要实现每一级抽象类的抽象方法
  • 接口可以有常量成员、抽象方法、默认方法、静态方法
    • 接口默认是 abstract
    • 接口的方法默认是 public abstract
    • 接口的常量成员默认是 public static final 的,也必须是这样的
    • 默认方法需要用 default 关键字修饰
    • 一个类可以实现多个接口

内部类

  • 内部类可以是抽象类,或者是接口
  • 成员内部类
    • 类似成员,可以有各种访问权限
    • 可以访问外部类的任何成员(包括 private 成员,就好比一个类的成员函数也可以访问这个类的 private 成员)
    • 通过 foo.new Bar() 语法进行实例化
  • 局部内部类
    • 类似普通变量,不可以有访问权限
  • 匿名内部类
    • new 的时候临时定义的,不能有构造方法
    • new Temp() { ... } 语法进行声明与实例化
  • 静态内部类
    • 类似静态成员,可以有各种访问权限
    • 可以访问外部类的任何 static 成员
    • new Foo.Bar() 语法进行实例化