课后作业
1.
class Grandparent { public Grandparent() { System.out.println("GrandParent Created."); } public Grandparent(String string) { System.out.println("GrandParent Created.String:" + string); } } class Parent extends Grandparent { public Parent() { super("Hello.Grandparent."); System.out.println("Parent Created"); // super("Hello.Grandparent."); } } class Child extends Parent { public Child() { System.out.println("Child Created"); } } public class TestInherits { public static void main(String args[]) { Child c = new Child(); } }
运行结果:
结果分析:
创建Child对象时,先调用GrandParent的构造方法,接着调用了Parent的构造方法,接着调用Child的构造方法
对Parent进行以下更改后
会出现以下错误信息:
也就是说通过 super 调用基类构造方法,必须是子类构造方法中的第一个语句。
2、
public class ExplorationJDKSource { /** * @param args */ public static void main(String[] args) { System.out.println(new A()); } } class A{}
运行结果:
System.out.println()会调用A类的toString()方法,
可A类里面没有定义toString()方法,但所有类都继承自Object类,Object内存在着toString()方法,会输出类名以及@哈希值
于是就会输出A@404b9385的结果
class Animal { // 父类的方法具有protected访问权限 protected void makeSound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { // 子类中的方法的访问权限不能小于父类中的方法 // 下面的代码会导致编译错误,因为覆盖的方法的访问权限比父类的方法的访问权限更严格(private < protected) private void makeSound() { System.out.println("Dog barks"); } }
(2)覆盖方法所抛出的异常不能比原方法更多
class Parent { // 父类方法声明抛出IOException void doSomething() throws IOException { // 省略具体实现 } } class Child extends Parent { // 子类方法声明抛出IOException和SQLException,这是不允许的 @Override void doSomething() throws IOException, SQLException { // 省略具体实现 } }
class Parent { // 使用final关键字声明的方法 public final void finalMethod() { System.out.println("This is a final method in the Parent class."); } } class Child extends Parent { // 尝试覆盖父类的final方法,会导致编译错误 // @Override // public void finalMethod() { // System.out.println("This is an attempt to override the final method."); // } } public class Main { public static void main(String[] args) { Parent parent = new Parent(); parent.finalMethod(); // 输出: This is a final method in the Parent class. Child child = new Child(); child.finalMethod(); // 调用继承的final方法,输出同样的结果 } }
在Java中,使用final
关键字声明的方法表示该方法是最终方法,不允许被子类覆盖(即不允许子类中有相同方法签名的方法覆盖该方法)。这是一种限制,通常用于确保特定方法在继承关系中具有不变性和稳定性。
class Parent { static void staticMethod() { System.out.println("父类的静态方法"); } } class Child extends Parent { static void staticMethod() { System.out.println("子类的静态方法"); } } public class Main { public static void main(String[] args) { Parent.staticMethod(); // 调用父类的静态方法 Child.staticMethod(); // 调用子类的静态方法 // 输出: // 父类的静态方法 // 子类的静态方法 } }
在Java中,静态方法是属于类的方法,而不是属于实例对象的方法。因此,静态方法不能被覆盖(override)。当子类中定义了一个与父类中的静态方法具有相同方法签名的静态方法时,实际上是隐藏了父类的静态方法,而不是覆盖了它。
在上面的例子中,虽然子类Child中定义了一个与父类Parent中的静态方法相同的静态方法staticMethod(),但它并没有覆盖父类的静态方法。在调用Child.staticMethod()时,实际上调用的是子类的静态方法,而不是父类的静态方法。
4.
class Mammal {} class Dog extends Mammal {} class Cat extends Mammal{} public class TestCast { public static void main(String args[]) { Mammal m; Dog d = new Dog(); Cat c = new Cat(); m = d; // 此行没有问题,将Dog对象赋给Mammal类型的变量 d = m; // 编译错误,不能将Mammal类型的变量赋给Dog类型的变量 d = (Dog) m; //运行时错误,会抛出异常,不能将父类强转为子类 d = c; // 编译错误,不能将Cat类型的变量赋给Dog类型的变量 c = (Cat) m; //运行时错误,会抛出异常,不能将父类强转为子类
} }
5、
运行结果:
首先创建了一个Parent
类的实例parent
,并调用了它的printValue()
方法,输出结果是Parent.printValue(), myValue=100
。接着,创建了一个Child
类的实例child
,并调用了它的printValue()
方法,输出结果是Child.printValue(), myValue=200
。
然后,将child
赋值给parent
,这样parent
引用指向了一个Child
对象。在Java中,实例变量(非静态变量)的访问是基于引用类型的,而不是实际对象的类型。所以,当调用parent.printValue()
时,它实际上调用的是Child
类中的printValue()
方法,输出结果是Child.printValue(), myValue=200
。
接着,parent.myValue++
会使用Parent
类中的myValue
变量,它的值会被增加到101
。因此,再次调用parent.printValue()
时,输出结果是Child.printValue(), myValue=200
,因为Child
类中的myValue
变量的值没有改变。
最后,通过强制类型转换((Child)parent).myValue++
,将parent
引用强制转换为Child
类型,并增加myValue
变量的值,使其变为201
。再次调用parent.printValue()
时,由于引用类型是Child
,因此输出结果是Child.printValue(), myValue=201
。
总结:
如果子类被当作父类使用,则通过子类访问的字段是父类的!