第5章 初始化与清理
5.1 用构造器确保初始化
public class User {
public int age;
public User(){
System.out.println("User");
}
public User(int age){
this.age = age;
}
}
public static void main(String[] args) {
new User(); // User
new User(1);
}
// new表达式会返回对新建对象的引用,但是构造器本身并没有任何返回值。
5.2 方法重载
// 通过参数列表区分重载方法
public void f(String s){
System.out.println("字符串");
}
public void f(int i){
System.out.println("整型");
}
// 方法签名唯一确认方法:方法名([参数列表])
基本类型重载:
- 提升:小类型按照顺序提升类型以适应方法需要的类型,char会直接提升到int;
- 强转:大类型强转为适应方法的类型。
返回值不能区分重载方法:
void f(){};int f(){}
,f();
此时无法确认是哪个方法。
5.3 默认构造器
当无构造器时,编译器会自动创建一个无参构造器;当定义了构造器时(无论是否有参数)编译器都不会再创建构造器。
5.4 this关键字
// this:只能在方法内部使用,表示对“调用方法的那个对象”的引用
// 削皮工具类
public class Peeler {
public static Apple peel(Apple apple) {
System.out.println("削皮");
return apple;
}
}
// 苹果类
public class Apple {
public int i;
public String s;
public Apple(int i) {
// 当成员变量和局部变量重名时,用this.的方式表示
this.i = i;
}
public Apple(int i, String s) {
// 用于构造方法中,必须放在最前/只能用一个
this(i);
this.s = s;
}
public Apple getPeeled() {
// 用在其他类中的方法
Apple apple = Peeler.peel(this);
System.out.println("已削皮");
return apple;
}
public Apple add(int i) {
// 返回当前对象的引用
this.i += i;
return this;
}
}
// 用户类
public class User {
public void eat(Apple apple){
Apple peeled = apple.getPeeled();
System.out.println("吃削皮的苹果");
}
}
// 测试
public static void main(String[] args) {
User user = new User();
Apple apple = new Apple(1);
outPut(apple.i); // 1
apple.add(1).add(2);
outPut(apple.i); // 4
user.eat(apple); // 削皮 已削皮 吃削皮的苹果
}
this的四种用法:
- 用在构造方法中;
- 返回当前对象的引用;
- 区分成员变量和局部变量;
- 用在其他类的方法中。
static方法中没有this关键字,通过类直接调用,这也正是它的用处。
5.5 清理:终结处理和垃圾回收(待做)
5.6 成员初始化
// 成员变量默认值
public class Admin extends User {
private char c;
private boolean falg;
private byte b;
private short s;
private int i;
private long l;
private float f;
private double d;
private Admin admin;
public void showDefaultValue(){
// 值为0,表现为空字符
System.out.println("char:[" +c+"]"); // char:[ ]
System.out.println("boolean:" + falg);// boolean:false
System.out.println("byte:"+b); // byte:0
System.out.println("short:"+s); // short:0
System.out.println("int:"+i); // int:0
System.out.println("long:"+l); // long:0
System.out.println("float:"+f); // float:0.0
System.out.println("double:"+d); // double:0.0
System.out.println("Admin:"+admin); // Admin:null
}
}
// 成员变量初始化
public class Admin extends User {
// 直接赋值
private int i = 1;
// 调用方法
private int j = f();
// 使用已定义的参数
private int a = f(j);
private Admin admin = new Admin();
private int f() {
return 1;
}
private int f(int i) {
return i;
}
}
5.7 构造器初始化
5.7.1 初始化顺序
public class Window {
public Window(int i){
System.out.println("window"+i);
}
}
public class House {
private Window w1 = new Window(1);
public House(){
System.out.println("house");
w2 = new Window(4);
}
private Window w2 = new Window(2);
private void f(){
}
private Window w3 = new Window(3);
}
public static void main(String[] args) {
House house = new House();
/*
window1
window2
window3
house
window4
*/
// 在创建对象时,先按照定义成员变量的顺序初始化成员变量,再执行构造器
}
5.7.2 静态数据的初始化
// 标识类
public class Window {
public Window(int i){
System.out.println("window"+i);
}
public void wf(int i){
System.out.println("wf"+i);
}
}
public class House {
private static Window w1 = new Window(1);
public House() {
System.out.println("house");
w2.wf(1);
}
private static Window w2 = new Window(2);
}
public class Building {
private static Window w3 = new Window(3);
private Window w4 = new Window(4);
public Building(){
System.out.println("building");
w6.wf(2);
w4 = new Window(5);
}
private static Window w6 = new Window(6);
}
// 测试类
public class Test {
public static void main(String[] args) {
Building building = new Building();
}
private static House house = new House();
}
/*
window1
window2
house
wf1
window3
window6
window4
building
wf2
window5
*/
执行顺序:
- 加载
Test
类,初始化静态成员变量house
; - 初始化House中的静态变量
w1
; - 执行
Window
构造方法打印window1
; - 初始化
House
中的静态变量w2
; - 执行
Window
构造方法打印window2
; - 执行
House
的构造方法打印house
并调用w2
的wf
方法打印wf1
; - 执行
main()
方法; - 加载
Building
类; - 初始化静态成员变量
w3
; - 执行
Window
构造方法打印window3
; - 初始化静态成员变量
w6
; - 执行
Window
构造方法打印window6
; - 初始化成员变量
w4
; - 执行
Window
构造方法打印window4
; - 执行
Building
构造方法打印building
并调用w6
的wf
方法打印wf2
; - 执行
Window
构造方法打印window5
;
5.7.3 显式的静态初始化
public class House {
public static Window w1;
// 静态语句块
static {
w1 = new Window(1);
Window w2 = new Window(2);
}
}
public static void main(String[] args) {
House.w1.wf(1);
House house = new House();
}
/*
window1(仅打印一次)
window2(仅打印一次)
wf1
*/
类初始化顺序:
- 首次: 加载类->初始化静态成员变量->初始化成员变量->执行构造方法;
- 非首次: 初始化成员变量->执行构造方法;
5.7.4 非静态实例初始化
public class House {
public Window w1;
{
w1 = new Window(1);
Window w2 = new Window(2);
}
public House(){
Window w3 = new Window(3);
}
}
public class Test {
public static void main(String[] args) {
House house = new House();
}
}
/*
window1
window2
window3
*/
5.8 数组初始化
数组初始化的三种方式
public static void main(String[] args) {
// 第一种(引用和创建数组不能分离)
int[] a1 = {1, 2, 3};
// 第二种
int[] a2 = new int[3];
for (int i = 0; i < a2.length; i++) {
a2[i] = i + 1;
}
// 注意:执行完for循环,第二种方式才初始化完毕
// 第三种
int[] a3 = new int[]{3, 4, 5};
}
可变参数列表
可传入参数:
public static void main(String[] args) {
Integer[] a = {1,2,3};
// 可以传入0个、多个、数组形式参数
f();
f(1,2,3);
f(a);
}
static void f(Integer... i) {
System.out.println(i.getClass());
for (Integer integer : i) {
System.out.println(integer.getClass());
}
}
重载:
public static void main(String[] args) {
// 这是错误的,编译器不知道选择哪个方法
//! f();
}
static void f(Integer... i) {
}
static void f(String... str) {
}
// 可变参数需要放在最后,倒数第二个参数不能是可变参数的类型
static void f(int i, String... str) {
}
5.9 枚举类型
public enum NameEnum {
DING,FU,JING
}
public static void main(String[] args) {
// 创建枚举的引用,引用枚举的一个值
NameEnum nameEnum = NameEnum.DING;
// 重写了toString()方法
System.out.println(nameEnum); // DING
// ordinal()方法返回在枚举中的声明顺序
System.out.println(nameEnum.ordinal()); // 0
}