定义:继承(inheritance):从已有的类派生出新的类。
继承可以让你定义一个通用的类,该通用类包含一些不同类的公共特征和动作;以该通用类扩展别的特定的类。
如果一个类c1继承于类c2,那么c1称为次类(subclass)或者子类(child class)、扩展类(extended class)、派生类(derived class);C2称为超类(superclass)或者父类(parent class)、基类(base class)。
子类可以从其父类中继承可以访问的数据域和方法,还可以添加新的数据域和新方法。
继承的实例:先创建一个通用的几何类,由几何类派生出圆、和矩形类:
几何类(基类):
package demo; /** * GeometricObject
* Created by luts on 2015/11/28. */ public class GeometricObject { private String color = "white"; private boolean filled; private java.util.Date dateCreadted; public GeometricObject(){ dateCreadted = new java.util.Date(); } public GeometricObject(String newColor, boolean newFilled){ dateCreadted = new java.util.Date(); this.color = newColor; this.filled = newFilled; } public String getColor(){ return color; } public void setColor(String newColor){ this.color = newColor; } public boolean isFilled(){ return filled; } public void setFilled(boolean newFilled){ this.filled = newFilled; } public java.util.Date getDateCreadted(){ return dateCreadted; } public String toString(){ return "creadted on " + dateCreadted + "\ncolor: " + color + " and filled: " + filled; } }
圆类(子类):
package demo; /** * cricle * Created by luts on 2015/11/28. */ public class Circle extends GeometricObject { private double radius; public Circle(){ } public Circle(double newRadius){ this.radius = newRadius; } public Circle(double newRadius, String newColor, boolean newFilled){ this.radius = newRadius; setColor(newColor); setFilled(newFilled); } public double getRadius(){ return radius; } public double getArea(){ return radius * radius * Math.PI; } public double getDiameter(){ return 2 * radius; } public double getPerimeter(){ return 2* radius * Math.PI; } public void printCircle(){ System.out.println("The circle is creadted " + getDateCreadted() + " and the raius is " + radius); } }
矩形类(子类):
package demo; /** * Rectangle extends from GeometricObject * Created by luts on 2015/11/28. */ public class Rectangle extends GeometricObject{ private double width; private double height; public Rectangle(){ } public Rectangle(double newWidth, double newHeight){ this.width = newWidth; this.height = newHeight; } public Rectangle(double newWidth, double newHeight, String newColor, boolean newFilled){ this.width = newWidth; this.height = newHeight; setColor(newColor); setFilled(newFilled); } public double getWidth(){ return width; } public void setWidth(double newWidth){ this.width = newWidth; } public double getHeight(){ return height; } public void setHeight(double newHeight){ this.height = newHeight; } public double getArea(){ return width * height; } public double getPerimeter(){ return 2 * (width + height); } }
测试类:
package demo; /** * test for circle and rectangle * Created by luts on 2015/11/28. */ public class TestCircleRectangle { public static void main(String[] args){ //create a circle Circle circle = new Circle(1); System.out.println("A circle "+ circle.toString()); System.out.println("The radius is: " + circle.getRadius() + "\nThe area is: " + circle.getArea()); System.out.println("The diameter is: "+ circle.getPerimeter()); //create a rectangle Rectangle rectangle = new Rectangle(2,4); System.out.println("\nA rectangle "+ rectangle.toString()); System.out.println("The area is: " + circle.getArea()); System.out.println("The diameter is: "+ rectangle.getPerimeter()); } }
输出结果:
A circle creadted on Sat Nov 28 10:27:04 CST 2015 color: white and filled: false The radius is: 1.0 The area is: 3.141592653589793 The diameter is: 6.283185307179586 A rectangle creadted on Sat Nov 28 10:27:04 CST 2015 color: white and filled: false The area is: 3.141592653589793 The diameter is: 12.0
Circle和Rectangle类继承GeometricObject类中所有可以访问的数据域和方法,另外两个类都重新定义了属于自己的求面积和周长的方法。GeometricObject类中的color和filled数据域是私有的,只能在GeometricObject类中访问,所有在子类中,如果要修改这两个属性,需要通过set和get方法。如:子类中重载的构造函数。
小结:
super关键字的作用:
super(); //调用父类的无参构造方法 super(parameter); //调用父类的有参构造方法
语句super()或super(参数)必须出现在子类构造方法的第一行,这是显示调用父类构造方法的唯一方法。
例如上例中的circle类中的一个含参构造方法可以替换为:
//原来的定义 public Circle(double newRadius, String newColor, boolean newFilled){ this.radius = newRadius; setColor(newColor); setFilled(newFilled); } //调用父类的构造方法 public Circle(double newRadius, String newColor, boolean newFilled){ super(newColor, newFilled); this.radius = newRadius; }
注意: 1. 要调用父类的构造方法必须使用super关键字,而且调用super语句必须是子类构造方法的第一条语句。在子类中调用父类的构造方法的名字会引起语法错误。
2. 构造方法可以用来构造一个类的实例。父类的构造方法不能被子类继承,只能通过super关键字调用。
3. 构造方法可以调用重载的构造方法或者其父类的构造方法。如果没有显示的调用,编译器会自动将super()作为构造方法的第一条语句:
public ClassName() { } 等价于: public ClassName() { super(); } public ClassName(double a) { } 等价于: public ClassName(double a) { super(); }
4. 构造一个类的实例的时候,将会调用沿着继承链的所有父类的构造方法。——构造方法链
super关键字不仅可以调用父类的构造方法,还可以调用父类的方法:
super.方法名 (参数);
例如上例中的Circle类的一个方法: public void printCircle(){ System.out.println("The circle is creadted " + getDateCreadted() + " and the raius is " + radius); } 可以写出: public void printCircle(){ System.out.println("The circle is creadted " + super.getDateCreadted() + " and the raius is " + radius); }
方法覆盖(method overriding):当子类需要修改父类中的方法实现。
例如上例中的GeometricObject中的toString方法返回的是几何对象的字符串,这个方法在Circle中可以被覆盖:
public String toString(){ return super.toString() + "\nradius is " + radius; }
注意:· 1)仅当实例方法是可被访问的时候,它才能被覆盖。父类中的私有方法不能被子类覆盖。
· 2)虽然静态方法也能被子类继承,但是不能被覆盖。如果父类中的静态方法被子类重新定义,那么父类中的静态方法会被隐藏。可以使用:父类名.静态方法名(SuperClassName.staticMethodName)来调用静态方法。
重载(overload):对于类的方法(包括从父类中继承的方法),方法名相同,参数列表不同的方法之间就构成了重载关系。
----参数列表又叫参数签名,包括:参数的类型,参数的个数,参数的顺序。这三者只要有一个不同就叫做参数列表不同。
覆盖 (override):也叫重写,就是在当父类中的某些方法不能满足要求时,子类中改写父类的方法。当父类中的方法被覆盖了后,除非用super关键字,否则就无法再调用父类中的方法了。
发生覆盖的条件:
· 1、子类和父类的方法名称,参数列表,返回类型必须完全相同,而且子类方法的访问修饰符的权限不能比父类低。
· 2、子类方法不能抛出比父类方法更多的异常。即子类方法所抛出的异常必须和父类方法所抛出的异常一致,或者是其子类,或者什么也不抛出;
· 3、被覆盖的方法不能是final类型的。因为final修饰的方法是无法覆盖的。
· 4、被覆盖的方法不能为private。否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。
· 5、被覆盖的方法不能为static。所以如果父类中的方法为静态的,而子类中的方法不是静态的,但是两个方法除了这一点外其他都满足覆盖条件,那么会发生编译错误。反之亦然。即使父类和子类中的方法都是静态的,并且满足覆盖条件,但是仍然不会发生覆盖,因为静态方法是在编译的时候把静态方法和类的引用类型进行匹配。
方法的覆盖和重载具有以下相同点:
· 都要求方法同名
· 都可以用于抽象方法和非抽象方法之间
方法的覆盖和重载具有以下不同点:
-- 方法覆盖要求参数列表(参数签名)必须一致,而方法重载要求参数列表必须不一致。
-- 方法覆盖要求返回类型必须一致,方法重载对此没有要求。
-- 方法覆盖只能用于子类覆盖父类的方法,方法重载用于同一个类中的所有方法(包括从父类中继承而来的方法)
-- 方法覆盖对方法的访问权限和抛出的异常有特殊的要求,而方法重载在这方面没有任何限制。
-- 父类的一个方法只能被子类覆盖一次,而一个方法可以在所有的类中可以被重载多次。
覆盖:
public class Test{ public static void main(String[] args){ A.a = new A(); a.p(10); a.p(10.0); } class B{ public void p(double i){ System.out.println(i * 2); } } class A extends B(){ public void p(double i){ System.out.println(i); } } }
上述程序运行输出都是10.0。因为调用的都是A中定义的p (double i)方法。
重载:
public class Test{ public static void main(String[] args){ A.a = new A(); a.p(10); a.p(10.0); } class B{ public void p(double i){ System.out.println(i * 2); } } class A extends B(){ public void p(int i){ System.out.println(i); } } }
输出:10 //调用A类中的p(int i)方法
20.0 //调用B类中的p(double i)方法
java中的每个类都起源于java.lang.Object类。如果一个类没有指定继承性,那么其父类就是Object类。
Object的toString()方法返回描述一个对象的字符串。
上例中的GeometricObject类重新了toString()方法:
public String toString(){ return "creadted on " + dateCreadted + "\ncolor: " + color + " and filled: " + filled; }
多态:父类型的变量可以引用子类型的对象。
先看两个概念:声明类型和实际类型。声明类型是变量被声明的某种类型,实例可以用声明类型或者其子类型的构造方法创建。实际类型是被变量引用的对象的实际类。
Object a = new GeometricObject(); System.out.println(a.toString());
这里a声明的类型是Object,实际类型是GeometricObject,a指向使用new GeometricObject()创建的对象。a调用的是实际类型中的toString()方法。
多态存在的三个必要条件
1、要有继承;
2、要有重写;
3、父类引用指向子类对象。
package demo; /** * Created by luts on 2015/11/28. */ public class DynamicBindingDemo { public static void main(String[] args) { m(new GraDuateStudent()); m(new Student()); m(new Person()); m(new Object()); } public static void m(Object x) { System.out.println(x.toString()); } } class GraDuateStudent extends Student{ } class Student extends Person{ public String toString(){ return "Student"; } } class Person extends Object{ public String toString(){ return "Person"; } }
输出:
Student
Student
Person
java.lang.Object@1540e19d
语句 Object a = new Student() 是合法的,称为隐式转换。---(1)
Student b = (Student) a; 称为显式转换。------(2)
(1)将一个子类的实例转换为一个父类的变量,称为向上转换,是可行的,因为子类的实例也是父类的实例。
(2)当把一个父类的实例转换成它的子类变量的时候(向下转换),必须使用“(子类名)”进行显示转换。
进行类型转换是因为在编译时声明类型决定了匹配的方法。通常将变量定义为父类型,这样就可以接收任何子类型的值。
instanceof运算符用于判断两个变量是不是同一类型。
object 的equals方法:测试两个对象是否相等。
object中的equals方法的签名: public boolean equals(Object obj){ return (this == obj) } 调用语法: object1.equals (object2)
这里的 == 比较运算符用来比较两个基本数据类型是否相等,或者判断两个对象是否具有相同的引用。
原文:http://www.cnblogs.com/luts/p/5002650.html