首页 > 代码库 > 接口与继承
接口与继承
1. 继承条件下的构造方法调用
(1)源代码
package demo1;
//一级级的调用,构造时先调用基类的构造函数;
//super
//构造函数调用必须是构造函数中的第一个语句
class Gradeparent
{
public Gradeparent()//默认构造函数
{
System.out.println("Gradeparent Created");
}
public Gradeparent(String string)//重载
{
System.out.println("Gradeparent Created.String"+string);
}
}
class Parent extends Gradeparent
{
public Parent()
{
//super(" hello ");
System.out.println("Parent Created");
}
}
class Child extends Parent
{
public Child()
{
System.out.println("Child Created");
}
}
public class TestInherits {
public static void main(String args[])
{
Child c=new Child();
}
}
(2)设计思想
先定义一个Gradeparent类,再定义一个Parent,直接继承Gradeparent,定义一个Child类,直接继承Parent类,为了看调用顺序,所以在每个构造函数中都有输出语句,用于判别是哪个先输出的,先调用的哪个;如果类中有无参构造函数和有参构造函数,默认的是无参构造函数,要是想调用父类的构造函数,可以用super。
(3)程序结果截图
第一个是没有用super,第二个用到了super,super()括号中有参数,所以就调用了有参数的基类构造方法。
(4)结论
父类与子类之间构造方法的调用关系修改Parent构造方法的代码,显式调用GrandParent的另一个构造函数,注意这句调用代码是否是第一句,影响重大!
通过 super 调用基类构造方法,必须是子类构造方法中的第一个语句。继承基类的方法是加extends关键词。
2. 为什么子类的构造方法在运行之前,必须调用父类的构造方法?能不能反过来?为什么不能反过来
构造函数的作用就是初始化,就像亲属关系中,只有有了父亲,才会有孩子,不能反过来。
3. 何为“不可变的类”?
创建“不可变的类”的对象后,此对象的属性不可改,而且也无法从此类派生出新子类。String就是一个典型的例子。不可变的“类”可以方便和安全地用于多线程环境中,访问它们可以不用加锁,因而能提供较高的性能。
(1)源程序
public final class Address
{
private final String detail;
private final String postCode;
//在构造方法里初始化两个实例属性
public Address()
{
this.detail = "";
this.postCode = "";
}
public Address(String detail , String postCode)
{
this.detail = detail;
this.postCode = postCode;
}
//仅为两个实例属性提供getter方法
public String getDetail()
{
return this.detail;
}
public String getPostCode()
{
return this.postCode;
}
//重写equals方法,判断两个对象是否相等。
public boolean equals(Object obj)
{
if (obj instanceof Address)
{
Address ad = (Address)obj;
if (this.getDetail().equals(ad.getDetail()) && this.getPostCode().equals(ad.getPostCode()))
{
return true;
}
}
return false;
}
public int hashCode()
{
return detail.hashCode() + postCode.hashCode();
}
}
(2)设计思想
定义不允许继承的类,类中有两个参数,一个无参数一个有参数,进行方法的重载,类中有两个实例属性,还有get函数,得到实例属性,equals方法判断对象是否是相等
4.为什么会输出这样的结果
(1)源程序
package demo1;
public class ExplorationJDKSource {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println(new A());
}
}
class A{}
(2)截图
(3)结果分析
前面示例中,main方法实际上调用的是:
public void println(Object x),这一方法内部调用了String类的valueOf方法。
valueOf方法内部又调用Object.toString方法:
public String toString() {
return getClass().getName() +"@" +
Integer.toHexString(hashCode());
}
hashCode方法是本地方法,由JVM设计者实现:
public native int hashCode();
5. 方法覆盖
(1)源代码
//抽象类和接口的设计
//陈晓阳 2016.11.11
public class Shape {
public static void main(String args[])
{
Rectangle a=new Rectangle(3,4);
System.out.print("面积"+a.getArea());
}
/*void showArea()//抽象方法,求面积并且显示
{
}*/
}
interface DiagArea//定义接口类
{
double getDiagonal();//求对角线长度方法
double getArea();//求面积
}
class Rectangle implements DiagArea//矩形类,实现接口
{
int a,b;//表示长和宽
Rectangle()
{
a=0;b=0;
}
Rectangle(int a1,int b1)
{
a=a1;b=b1;
}
public double getDiagonal()//覆盖,求对角线长
{
return Math.sqrt(a*a+b*b);
}
public double getArea()//覆盖,求面积
{
return a*b;
}
}
class Square extends Rectangle//正方形继承矩形类
{
int x;//正方形的边
//构造函数,进行初始化
Square()
{
x=0;
}
Square(int aa)
{
a=aa;
}
public double getDiagonal()//求对角线
{
return Math.sqrt(a*a*2);
}
public double getArea()//求面积
{
return a*a;
}
void display()//显示边长、面积、对角线长
{
System.out.println("正方形的边长、面积、对角线分别是:");
System.out.println(x+" "+getArea()+" "+getDiagonal());
}
}
//class Circle
(2)设计思想
定义一个接口,里面有一些函数,实现接口,在里面实现覆盖,接着在主方法中定义变量,调用覆盖后的结果。
(3)截图
(4)编译错误,注意事项
覆盖方法的允许访问范围不能小于原方法。覆盖方法所抛出的异常不能比原方法更多。声明为final方法不允许覆盖。例如,Object的getClass()方法不能覆盖。不能覆盖静态方法,覆盖时要用public。
接口与继承