10.24 10.20课后作业

构造方法调用关系验证
子类构造方法必须先调用父类构造方法,且super()必须是子类构造方法第一句
// 祖父类
class GrandParent {
// 无参构造
public GrandParent() {
System.out.println("GrandParent: 无参构造");
}
// 带参构造
public GrandParent(String msg) {
System.out.println("GrandParent: 带参构造,消息:" + msg);
}
}

// 父类
class Parent extends GrandParent {
// 无参构造(默认调用父类无参构造)
public Parent() {
// 显式调用GrandParent的带参构造,必须放在第一句
super("父类调用祖父类带参构造");
System.out.println("Parent: 无参构造");
}
}

// 子类
class Child extends Parent {
public Child() {
// 隐式调用Parent的无参构造,若加super()需放在第一句
System.out.println("Child: 无参构造");
}
}

// 测试类
public class TestInherits {
public static void main(String[] args) {
new Child();
// 预期输出顺序:
// GrandParent: 带参构造,消息:父类调用祖父类带参构造
// Parent: 无参构造
// Child: 无参构造
}
}
若将super("xxx")从 Parent 构造方法的第一句移到第二句,编译直接报错,验证 “super()必须是第一句” 的语法规则。
移除 Parent 中的super(...),则默认调用 GrandParent 的无参构造,输出顺序变为 “GrandParent 无参→Parent 无参→Child 无参”,验证 “子类默认调用父类无参构造” 的规则。
2.
对象创建后属性不可修改,且无法被继承。
// 不可变类:final修饰类(无法继承),属性private final(不可修改)
final class Address {
private final String province;
private final String city;

// 构造方法初始化所有属性(唯一赋值机会)
public Address(String province, String city) {
    this.province = province;
    this.city = city;
}

// 只提供getter,不提供setter(避免修改属性)
public String getProvince() {
    return province;
}

public String getCity() {
    return city;
}

// 重写toString方便查看
@Override
public String toString() {
    return province + "-" + city;
}

}

// 测试类
public class TestImmutable {
public static void main(String[] args) {
Address addr = new Address("河北省", "石家庄市");
System.out.println(addr); // 输出:河北省-石家庄市

    // 验证1:无法修改属性(无setter,且属性final)
    // addr.setProvince("北京市"); // 编译报错:无此方法
    // addr.province = "北京市"; // 编译报错:final属性不可修改

    // 验证2:无法继承(类final)
    // class SubAddress extends Address {} // 编译报错:无法继承final类
}

}
不可变类需满足 3 个条件:final修饰类、所有属性private final、仅提供 getter 无 setter。
对比String类:String str = "abc"; str += "d";本质是创建新String对象("abcd"),原对象 "abc" 未被修改,验证不可变特性。
3.
覆盖(Override) 和 重载(Overload) 的语法差异
class ParentMethod {
// 父类方法:访问权限protected,无异常,非静态
protected void show(String msg) {
System.out.println("Parent: " + msg);
}

// 父类静态方法
public static void staticMethod() {
    System.out.println("Parent static method");
}

}

class ChildMethod extends ParentMethod {
// 1. 方法覆盖(Override):方法签名完全一致(方法名、参数列表、返回值)
@Override // 注解校验是否为有效覆盖,错误时编译报错
public void show(String msg) { // 访问权限≥父类(protected→public,合法)
// 若改为private void show(...):编译报错(访问权限缩小)
System.out.println("Child: " + msg);
}

// 2. 方法重载(Overload):方法名相同,参数列表不同(参数类型/个数)
public void show(int num) {
    System.out.println("Child overload: " + num);
}

// 3. 静态方法无法覆盖:子类静态方法与父类静态方法仅为“隐藏”,非覆盖
public static void staticMethod() {
    System.out.println("Child static method");
}

}

// 测试类
public class TestOverrideOverload {
public static void main(String[] args) {
ParentMethod parent = new ChildMethod(); // 多态:父类引用指向子类对象

    // 验证覆盖:调用子类重写的show(String)
    parent.show("Hello"); // 输出:Child: Hello
    
    // 验证重载:父类引用无法调用子类独有的重载方法(编译报错)
    // parent.show(123); 
    ChildMethod child = new ChildMethod();
    child.show(123); // 输出:Child overload: 123(子类对象可调用)
    
    // 验证静态方法隐藏:调用父类还是子类静态方法,由“引用类型”决定(非多态)
    parent.staticMethod(); // 输出:Parent static method(父类引用→父类静态方法)
    child.staticMethod();  // 输出:Child static method(子类引用→子类静态方法)
}

}
覆盖要求:方法签名完全一致、访问权限≥父类、异常≤父类、非静态方法;违反则编译报错。
重载要求:仅需方法名相同,参数列表不同(与返回值、访问权限无关)。
静态方法无多态:调用哪个版本由 “引用类型” 决定,而非 “对象真实类型”。
4.
多态仅作用于方法,不作用于字段
class Parent {
public int myValue = 100;

public void printValue() {
    System.out.println("Parent.printValue(), myValue=" + myValue);
}

}

class Child extends Parent {
public int myValue = 200; // 子类与父类同名字段(隐藏父类字段)

@Override
public void printValue() {
    System.out.println("Child.printValue(), myValue=" + myValue); // 访问子类字段
}

}

public class ParentChildTest {
public static void main(String[] args) {
// 1. 父类对象调用
Parent parent = new Parent();
parent.printValue(); // 输出:Parent.printValue(), myValue=100(父类方法+父类字段)

    // 2. 子类对象调用
    Child child = new Child();
    child.printValue(); // 输出:Child.printValue(), myValue=200(子类方法+子类字段)

    // 3. 多态:父类引用指向子类对象
    parent = child;
    parent.printValue(); // 输出:Child.printValue(), myValue=200(子类方法,多态生效)

    // 4. 访问字段:由“引用类型”决定(无多态)
    parent.myValue++; // 修改的是父类字段(parent是Parent类型)
    System.out.println("parent.myValue=" + parent.myValue); // 输出:parent.myValue=101
    parent.printValue(); // 输出:Child.printValue(), myValue=200(子类方法仍访问子类字段)

    // 5. 强制类型转换后访问子类字段
    ((Child) parent).myValue++; // 转换为Child类型,访问子类字段
    System.out.println("((Child)parent).myValue=" + ((Child) parent).myValue); // 输出:201
    parent.printValue(); // 输出:Child.printValue(), myValue=201(子类方法访问修改后的子类字段)
}

}
多态仅作用于方法:父类引用指向子类对象时,调用的是子类重写的方法(由对象真实类型决定)。
字段无多态:访问字段由引用类型决定,父类引用访问父类字段,子类引用访问子类字段(即使是同一个对象)。

posted @ 2025-10-24 15:26  GENGAR-  阅读(8)  评论(0)    收藏  举报