slacr_

Just to record my life and thoughts.
笔记/编程/杂乱/极简

[Java笔记]类&对象

May 3, 2023Java2127 words in 14 min

类的定义

1
2
3
4
5
[public][abstract | final] class ClassName [extends SuperClass] [implements InterfaceNameList]{ 

// class body...

}

类访问修饰符可以是public或缺省, 使用public, 则称之公共类, 公共类可以被任何包中的类使用, 若不加public修饰符, 只能被同一包中的其他类使用.

一个project中只能有一个主类和主方法.
一个源文件中只能有一个public类, 其他类的个数不限.

在练习的时候为了方便在一个project中放入多个主类, 我们可以为每次的代码单独建一个包, 一个包可以包含多个源文件, 包的名称不像类的名称严格限定必须和源文件中类名相同, 更改灵活. 这个包中可以写主类和主方法来测试各个类. 虽然在每个源文件中也可以写主方法那是因为主方法是静态的, 无需实例化在编译时就可以确定入口. 但这并不符合认知逻辑, 一个类应该只完成该类的功能, 主方法就应该放在完成程序执行功能的主类中.

成员变量的定义

1
[public | protected | private] [static] [final] type variableName[=value];

用 public修饰的变量为公共变量,公共变量可以被任何方法访问;用protected修饰的变量称为保护变量,保护变量可以被同一个包中的类或子类访问;没有使用访问修饰符,该变量只能被同一个包中的类访问;用private修饰的变量称为私有变量,私有变量只能被同一个类的方法访问.

如果变量用static修饰,则该变量称为静态变量,又称为类变量。没有用 static修饰的变量称为实例变量

使用 final修饰的变量叫作最终变量,也称为标识符常量。常量可以在声明时赋初值, 也可以在后面赋初值,一旦为其赋值,就不能再改变了.

成员方法的定义

1
2
3
4
5
[public | protected | private]  [static] [final | abstract] returnType methodName ([paramList]){

// method body...

}

private方法只能在同一个类中被调用,protected方法可以在同一个类、同一个包中的类以及子类中被调用,而用 public修饰的方法可以在任何类中调用。一个方法如果缺省访问修饰符,则称包可访问的,即可以被同一个类的方法访问和同一个包中的类访问.

没有用 static修饰的方法称为实例方法,用 static修饰的方法称为静态方法。

用 final修饰的方法称为最终方法,最终方法不能被覆盖。方法的覆盖与继承有关。用 abstract修饰的方法称为抽象方法。

单例模式

在Java类的设计中,有时希望一个类在任何时候只能有一个实例,这时可以将该类设计为单例模式(singleton)。要将一个类设计为单例模式,类的构造方法的访问修饰符应声明为private, 然后在类中定义一个static方法,在该方法中创建类的对象.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Singleton {
private Singleton(){} // 构造函数
public int num = 0;
public void print(String s) {
System.out.println(s);
}
static final Singleton I = new Singleton(); // 唯一的实列对象
};

public class Main {
public static void main(String[] args) {
// Singleton s = new Singleton();
Singleton s1 = Singleton.I;
Singleton s2 = Singleton.I;
s1.print("good");
s1.num++;
s2.num++;
System.out.println(s1.num); // 2
System.out.println(s1==s2); // true
}
}

对象初始化值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class ObjInit {
int x = 1; // 默认初始化值1
static int y;
{
x = 2; // 初始化块初始化
System.out.println("x in initial block: " + x );
}
static { // 静态初始化块初始化静态变量
y = 20;
System.out.println("y in initial block: " + y );
}
public ObjInit(int x) {
this.x = x;
this.y = 30;
System.out.println("x in constructor: " + x );
System.out.println("y in constructor: " + y );
}
}

public class Main {
public static void main(String[] args) {
ObjInit o = new ObjInit(3);
System.out.println("x after constructor: " + o.x);
System.out.println("y after constructor: " + o.y);
}
}

当一个类有多种初始化方法时,执行顺序是:
(1)用默认值给静态变量赋值,然后执行静态初始化块为static变量赋值。
(2)用默认值给实例变量赋值,然后执行初始化块为实例变量赋值。
(3)最后使用构造方法初始化静态变量或实例变量。

垃圾回收GC

在 Java程序中,允许创建尽可能多的对象,而不用担心销毁它们。当程序使用一个对象后,该对象不再被引用时, Java运行系统就在后台自动运行一个线程,终结 (finalized) 该对象并释放其所占的内存空间,这个过程称为垃圾回收 (garbage collection,GC)。
后台运行的线程称为垃圾回收器 (garbage collector)。垃圾回收器自动完成垃圾回收操作,因此,这个功能也称为自动垃圾回收。所以,在一般情况下,程序员不用关心对象不被清除而产生内存泄露问题。

当一个对象不再被引用时,该对象才有可能被回收。一个对象可能有多个引用,只有在所有的引用都被删除,对象才有可能被回收。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Test {
public int num;
public Test(int num) { this.num = num; }
}
public class Main {
public static void main(String[] args) {
Test t1 = new Test(1);
Test t2 = t1;
t2.num = 100;
// Java中没有默认的复制构造, 不像C++
System.out.println(t1.num);

Test t3 = new Test(3);
t1 = t3;
t2 = t3;
System.gc(); // 启用垃圾回收器, 当不能保证立即回收
// Runtime rt = Runtime.getRuntime(); // 同上
// rt.gc();
}
}

如果希望及时回收对象, 可以调用System类的gc方法或Runtime类的gc方法.

包(package)

Java 语言使用包来组织类库,包 (package) 实际是一组相关类或接口的集合。
包是Java语言最大的封装单位,定义了程序对类的访问权限。

如果在定义类时没有指定类属于哪个包,则该类属于默认包 (default package), 即当前目录。默认包中的类只能被该包中的类访问。为了有效地管理类,通常在定义类时指定类属于哪个包,这可通过 package 语句实现.

如果一个类属于某个包,可以用类的完全限定名 (fully qualified name)来表示, 防止类名重复.

Java5 版中,允许使用 import static语句导入类中的常量和静态方法,再使用这些类中的常量或方法就不用加类名前缀了

使用java.lang 包和默认包(当前目录)中的类不需要使用 import语句将其导入,编译器会自动导入该包中的类.

知识点

  1. 把能够返回成员变量值的方法称为访问方法 (accessor method), 把能够修改成员变量值的方法称为修改方法 (mutator method)。 访问方法名一般为 getxx(), 因此访问方法也称 getter方法。修改方法名一般为 setxx(), 修改方法也称setter方法
  2. 函数执行时会创建一个活动记录(activation record), 它包括方法的参数、方法中声明的局部变量. 将其存储在栈中.
  3. 一旦定义了有参构造, 编译器就不再提供默认构造. 习惯写上默认构造.
  4. this关键字可以调用该类的另一个构造方法 this(value). 如果在构造方法中调用另一个构造方法,则 this语句必须是第一条语句.
  5. Java 语言规定,this只能用在非 static方法(实例方法和构造方法)中,不能用在 static方法中。实际上,在对象调用一个非 static方法时,向方法传递了一个引用,这个引用就是对象本身,在方法体中用 this表示。
  6. 静态成员能直接通过类名调用
    1
    2
    3
    4
    5
    6
    public class Main {
    public static void main(String[] args) {
    int rnum = (int)(Math.random()*100 + 1); // [1, 100]
    System.out.println(rnum);
    }
    }
  7. Java的作用域通过块(block)限定.

参考

  1. 《Java程序设计(第3版)》 IBSN 9787302485520
  2. Java API 文档
  • Author:

    slacr_

  • Copyright:

  • Published:

    May 3, 2023

  • Updated:

    May 3, 2023

Buy me a cup of coffee ☕.

1000000