Java笔记

基本概念

  • Java使用引用来操作对象。Java使用垃圾回收器来监视使用new创建的所有对象,辨明不再需要的对象,随后释放这些对象的内存空间。
  • Java类中的数据成员称为“字段”,成员函数称为“方法”。

代码组织

  • 每个.java文件是一个编译单元;一个编译单元中可以有多个类,但最多只有一个public类。当编译单元中存在public类时,编译单元的文件名需与public类类名保持一致;否则,文件名与编译单元内任意类名相同即可。
  • 使用命令行编译时,只需要指定编译入口类,编译器会自动编译所需的类。

数据类型

Java类中的数据成员称为“字段”,成员函数称为“方法”。

Compile

  • 可以使用source开关来指定目标JRE版本:-source 1.4

package

Java使用包来组织类。

运行有包名的主类时必须使用完全限定名称。

javac package/name/*.java
java package.name.MainClass

Chapter 2 数据类型

基本数据类型与它对应的包装:

  • boolean(Boolean), char(Character)
  • byte(Byte), short(Short), int(Integer), long(Long)
  • Type.MAX_VALUE, Type.MIN_VALUE
  • Type(Type num), Type.typeValue()
  • float(Float), double(Double), void(Void)
  • BigInteger, BigDecimal
  • 不会自动地将数值转换为Boolean值。

处理较大数据时使用的:BigInteger, BigDecimal

包装器方法

  • Integer等 toString(), toBinaryString()
  • Character isLowerCase()

字面值书写

  • 整数计数法与C++形式相同,支持十进制、八进制和十六进制。
  • 指数计数法与C++形式相同。

赋值

  • 对基本类型的赋值是按值传递,对对象“赋值”时传递的是引用。
  • 别名现象 按值传递,导致传递的是引用而不是复制对象。

数组

不允许指定数组的大小,因为Java只持有引用。

int[] arr = {... };  // 推荐,花括号初始化等价于使用new
int arr[] = {... };  // 符合C/C++习惯
int[] arr = new int[元素个数];

使用花括号语法初始化对象数组

Integer[] arr = {
    new Integer(1),
    new Integer(2),
    3  // 自动装箱
};

每种类型的数组的固有对象是length,代表数组的长度。

对于高维数组,形式如下:

int dimTwo[][] = new int[3][4];

int dimTwo[][] = new int[3][];
dimTwo[0] = new int[1];
dimTwo[1] = new int[2];
dimTwo[3] = new int[3];

枚举Enum

public enum Currency {
    ONE, TWO, THREE
}

可以在switch中使用Enum,注意枚举中的使用不需要类型限定名

public class ShowCurrency {
    public static void main(String[] args)
    {
        Currency cur = Currency.ONE;
        switch(cur)
        {
        case ONE:
        case TWO:
        case THREE:
            System.out.println("This is a simple usage of Currency");
        }
    }
}

流程控制

Java中if-else, while, do-while, for, switch形式上与C++保持一致。

注意Java中的逗号操作符只在for中使用。

Java中的foreach与C++保持一致,形式上是for (char c : string)

“goto”与标签

Java中没有goto,但把breakcontinue结合标签使用

label1:
outer-iteration {
    // ...
    inner-iteration {
        // ...
        break;            // 跳出内层循环
        continue;         // 内层循环重新开始
        continue label1;  // 从外层循环重新开始
        break lable1;     // 结束外层循环
    }
}

合理利用可以减少flag的传递。

foreach

for (Type value : values) {
    // 循环体
}

初始化

  • 静态初始化 Java为类的基本数据成员提供默认的初始化,Java保证必要的初始化必须进行。
  • 指定初始化 在声明类成员处赋值。

可以使用static块组织静态初始化的代码:

static int i;
static {
    i = 12;
}

类中的静态成员也称为“类变量”。

构造器

基本内容与C++保持一致。

清理:终结处理和垃圾回收

Java中的finalize()方法会在对象被回收之前调用。

仅仅使用finalize()应对类似C语言的内存分配的清理工作,或者进行对象回收的“终结条件”验证。

使用System.gc()执行垃圾回收。

垃圾清理概要

  • 引用计数与堆栈或静态储存区追溯
  • “停止-赋值”、“标记-清理”
  • JIT(Just in time), lazy evalution

方法

可变参数列表

可变参数列表可以接受0个参数。

数组形式

void func(Object[] objs) {
    for (Object obj : objs) {
        // ...
    }
}

省略号语法

void func(Object... objs) {
    for (Object obj : objs) {
        // ...
    }
}

由于可变参数列表可以接受0个参数,Java中存在自动装箱机制,因此重载方法接受基本数据类型时可能遇到因为0个参数而无法判定调用哪个重载方法的问题。

instanceof操作符

左边的类是否为右边的类或子类创建的对象。

常用类

java.util.Arrays

  • Arrays.toString() 打印数组

java.util.Random

Random rand = new Random(47);
rand.nextInt(100);  // 生成[0, 100)区间内的随机数

java.io.BufferedReader

public static void main(String args[]) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader("ReadFile.java"));
    for (String line = br.readLine(); line != null; line = br.readLine()) {
        System.out.println(line);
    }
    br.close();
}

java.io.FileInputStream & java.io.FileOutputStream

FileInputStream in = new FileInputStream("CopyFile.java");
FileOutputStream out = new FileOutputStream("CopyFile.java.tmp");

int read = in.read();
while (read != -1) {
    out.write(read);
    read = in.read();
}

in.close();
out.close();

java.io.File

File[] files = new File(".").listFiles();
for (File file : files) {
    if (file.isDirectory()) {
        System.out.println("<DIR>" + file.getName());
    } else {
        System.out.println(file.getName());
    }
}

java.util.StringTokenizer

访问权限控制

  • Java没有条件编译,但可以通过import发行包和调试包来实现类似的功能

访问权限修饰词

  • public 接口访问权限
  • 无修饰词为**包访问权限**
  • protected 继承访问权限
  • private 封闭的访问权限

复用类(组合、继承与代理)

接口 interface

interface SomeInterface {
    // interface body
}

接口中的方法一定是public abstract

  • 若一个接口被public修饰,那么它可以被任何一个类实现。
  • 若一个接口没有被public修饰,那么它可以被同一包内的类实现。

继承

class Apple extends Fruit {
    // class definition
}

class Apple implements Etable {
    // class definition
}

类的继承对父类成员的访问权限符合访问权限限制,即:

  1. 当子类和父类在同一个包中时,子类自然地继承父类中不是private的成员。
  2. 当子类和父类在不同包中时,子类只能继承父类中public和protected的成员。

在继承中使用同名的变量时,父类同名变量隐藏,可以使用super.var访问。

在继承中使用同名的方法时,方法可以隐藏或重写。

对于重写,方法的类型与父类方法类型一致或者是父类方法类型的子类型。

使用@Override注记来指明对方法的重写。

重写父类方法时,不能降低父类方法的访问权限,这是从继承的角度看子类也是一种基类的限制。

abstract关键字

abstract class SomethingAbstract {
    abstract abstractMethod();

    nonAbstractMethod() {
        // function body.
    }
}
  • abstract类可以有抽象方法和非抽象方法。
  • abstract类不能使用new来创建对象。
  • 不能同时使用abstract和final来修饰同一个类。

final关键字

  • 先构建基类部分,再构建子类部分。
  • 在子类的构造器中初始化子类的代码之前,使用super()调用基类的构造器。

final数据

  • static final 编译器常量
  • final 运行期常量
  • final参数 方法中不可改变参数

final方法

  • 禁用重载

final类

  • 禁止继承

多态

Java中的多态性是“同名不同参,同名不同义”。

常见问题处理方式

数字格式

java.text.NumberFormat, java.text.DecimalFormat

每三位数字插入一个分隔符

NumberFormat formatter = new DecimalFormat(",###");
formatter.format(number)

输入输出工具

java.util.Scanner

Scanner sc = new Scanner(System.in);
sc.hasNext(); // ...
sc.NextInt(); // ...

System.out.printf(format-string, var-list)

类C语言的printf方法。


最后更新: 2019年11月28日