目录
一、类的继承
二、Object类
1. getclass()方法
2. toString()方法
3. equals()方法
三、对象类型的转换
四、使用instanceof操作符判断对象类型
五、方法的重载
定义不定长参数方法
六、多态
七、抽象类与接口
1、抽象类
2. 接口
3. 接口与继承
在subroutine.java中:
class Parent{
Parent(){
System.out.println("调用父类的Parent()构造方法");
}
}
class SubParent extends Parent{
SubParent(){
System.out.println("调用子类的subParent()构造方法");
}
}
public class subroutine extends SubParent {
subroutine(){
System.out.println("调用子类的subroutine()构造方法");
}
public static void main(String[] args) {
subroutine obj = new subroutine();
}
}
在实例化子类对象时,父类无参构造方法将被自动调用,但又参构造方法不能被自动调用。只能依赖于super关键字显式调用父类的构造方法。创建一个子类对象,将包含一个父类子对象。当实例化子类对象时,父类对象也相应被实例化。
(以下具体代码)
class text{
text(){
System.out.println("call the constructor of text()");
}
public void doSomething() {
System.out.println("doSomething");
}
protected text dolt() {
return new text();
}
}
public class text2 extends text{
text2(){
super();
System.out.println("call the constructor of text2()");
}
public void doSomething() {
System.out.println("doSomething in class text2");
}
public void doNew() {
System.out.println("doNew here");
}
protected text2 dolt() {
return new text2();
}
public static void main(String[] args) {
text2 obj = new text2();
obj.doSomething(); //执行text2类中的方法
obj.doNew();
obj.dolt(); //执行text2类中的方法
}
}
结果为:
call the constructor of text() | 创建父类对象 |
call the constructor of text2() | 创建子类对象 |
doSomething in class text2 | 调用text2中的重写方法 |
doNew here | 调用text2中新添加的方法 |
call the constructor of text() | 调用text2中的dolt()方法,创建对象,先创建一个父类对象 |
call the constructor of text2() | 再创建一个子类对象 |
1. super关键字:
可以在子类的构造方法中调用super()语句调用父类的构造方法;也可以在子类中使用super关键字调用父类的成员方法(仅public、protected)。
2. 重写(覆盖)父类的成员方法:
将父类成员方法的名称保留,
1)重写成员方法的实现内容 | |
2)更改成员方法的存储权限: | 只能从小范围改到大范围 |
3)修改成员方法的返回类型: | 遵循:重写的返回值类型必须是父类该方法的返回值类型的子类 |
重写方法的调用: |
||
1)用实例化对象是调用不到父类的 | 在内存中仍为子类对象 | |
2)只能用super关键字 | 1)且只能在类方法中调用 2)在main(类外部)是调用不到的 |
|
(最初overrride的设计意图之一) |
class Father{
Father(){}
public void doSth() {
System.out.println("doFather");
}
}
public class overrideDemo extends Father {
overrideDemo(){}
public void doSth() {
System.out.println("doOverride");
}
public void callFatherdoSth() {
super.doSth(); //用super关键字在子类类方法中调用父类重写方法
}
public static void main(String[] args) {
overrideDemo obj = new overrideDemo();
obj.doSth(); //调用子类方法
obj.callFatherdoSth(); //通过子类中的方法,调用父类重写方法
//不是用实例化对象调用的
//子类方法中用super关键字调用了重写方法
}
}
如果要调用父类的重写方法,就在子类中加一个方法,该方法用super关键字调用父类重写方法。若多重继承,也可以这样调用,在每个子类中都加上这样的方法就可以了。
如果要调用
3. 重构:
子类与父类的成员方法:返回值相同、方法名称相同、参数类型及个数相同;仅方法实现内容不同。
在Java中,所有类都直接或间接继承了java.lang.Object类。Object类是所有类的父类,是java类层中最高层类。
1)在Object类中主要包括equals()、toString()、clone()、finalize()等方法。由于所有类都是Object类的子类,所以任何类都可以重写Object类中的方法。
2)Object类中的getClass()、notify()、notifyAll()、wait()等方法不能被重写,因为这些方法被定义为final类型。
返回对象执行时的Class,然后使用此实例调用getName()方法,可以获得类的名称。还可与toString()方法联合使用
将一个对象返回为欸字符串形式,返回类型为String,返回一个String实例。实际中通常根据需要重写toString方法。
当对象转换为欸字符串或与字符串连接时,将自动调用重写的toString()方法。
public class ObjectInstance{
public String toString(){ //toString()返回一个String实例
return "在" + getClass().getName() + "类中重写toString()方法";
}
public static void main(String[] args){
ObjectInstance obj = new ObjectInstance();
System.out.println(obj); //自动调用重写的toString()方法
}
} //输出为:“在ObjectInstance类中重写toString()方法”
“==”比较的时两个引用是否相等,而equals()方法比较的是实际内容。
而在比较两个自定义类的实例化对象时,因为equals()方法的默认实现是使用“==”运算符比较两个对象的引用地址,而不是比较对象的内容,因此通常需要在自定义类中重写equals()方法。
class V_one{
public String name;
V_one(){}
V_one(String str){name = str;}
}
class V_two{
public String name;
V_two(){}
V_two(String str){name = str;}
public Boolean equals(V_two v) {
return name.equals(v.name);
}
}
public class OverWriteEquals {
public static void main(String[] args) {
String str1 = new String("123");
String str2 = new String("123");
V_one one1 = new V_one("ab");
V_one one2 = new V_one("ab");
V_two two1 = new V_two("cd");
V_two two2 = new V_two("cd");
System.out.println(str1.equals(str2)); //true
System.out.println(one1.equals(one2)); //false
System.out.println(two1.equals(two2)); //true,因为调用了重写的equals()方法
}
}
向上转型(将子类对象视为父类对象,自动)。子类对象都可以被看作是一个父类对象。
向下转型,往往会报错,要显式类型转换。在执行向下转型操作时,如果父类对象不是子类对象的实例,就会发生ClassCastException异常。
就像上面说的,此时,就要在执行向下转型之前,要习惯判断父类对象是否为子类对象的实例。
可以使用instanceof操作符判断是否一个类实现了某个接口(接口在后文),也可以用它来判断一个实例对象是否属于一个类。
myobject instanceof ExampleClass |
myobject:某类的对象引用
ExampleClass:某个类
返回值为布尔值
class AA{
//……
}
class BB extends AA{
//……
}
class CC{
//……
}
public class DD extends AA{
public static voiid main(String[] args){
AA a = new AA();
if(a instanceof DD){
DD d = (DD)a; //向下转型操作
}
if(a instanceof BB){
BB b = (BB)a; //向下转型操作
}
if(a instanceof CC){ //实例对象a不属于CC类
//……
}
}
}
方法的重载在就是在同一个类中允许同时存在一个以上的同名方法,只要这些方法的参数个数或类型不同即可。但只有返回类型不同也不行,还需要通过参数以及参数的类型来设置。(常规略)
不定长方法语法:
返回值 方法名(参数数据类型 ...参数名称) //3个英文句号
public class UncertainLengthAdd {
public static int add(int...a) {
int sum = 0;
for(int i=0;i
如果定义一个四边形类,让它处理所有继承该类的对象,根据”向上转型“原则可以使每个继承四边形类的对象作为draw()方法的参数,然后再draw()方法中作一些限定就可以根据不同图形类对象绘制相应的图形,从而以更为通用的四边形类来取代具体的正方形类和平行四边形类。这样处理就能够很好地解决代码冗余的问题,同时也易于维护。使得无需在所有子类中定义执行相同功能的方法。
在多态机制中,并不需要将弗雷初始化对象,需要的只是子类对象。会把子类对象都向上转型为父类对象来调用父类方法。
创建Quadrangle类,再分别创建两个内部类Square和Parallelogramgle,它们都继承了Quadrangle类。编写draw()方法,该方法接受Quadrangle类的对象作为参数,即使用这两个内部类的父类作为方法参数。在住方法中分别以两个内部类的实例对象作为参数执行draw()方法。
//定义一个正方形类,继承四边形类
class Square extends Quadrangle{
public Square() {
System.out.println("正方形");
}
}
//定义一个平行四边形类,继承四边形类
class Parallelogramgle extends Quadrangle{
public Parallelogramgle() {
System.out.println("平行四边形");
}
}
public class Quadrangle {
//实例化保存四边形对象的数组对象
private Quadrangle[] qtest = new Quadrangle[6];
private int nextIndex = 0;
public void draw(Quadrangle q) {
if(nextIndex
一般将父类定义为抽象类,需要使用这个父类进行继承与多态处理。在多态机制中,并不需要将父类初始化对象,需要的只是子类对象。所以java中,抽象类不可以实例化对象,其子类可以。
抽象类语法:------抽象类关键字abstract
public abstract class Test{
abstract void testAbstract(); //定义抽象方法
}
1、使用absract关键自定义的类称为抽象类,使用这个关键字定义的方法称为抽象方法。
2、抽象方法没有方法体。抽象方法只能定义在抽象类中。
3、承载抽象方法的抽象类必须被继承。
4、继承抽象类的所有子类必须重写抽象类中的所有抽象方法。保证相同的方法名称、参数列表和相同返回值类型。子类可以创建出非抽象方法,或者抽象方法。
---->当子类中的一部分需要一个方法,而另一部分不需要这一方法时(如果在父类抽象类中定义该方法,那么不需要这个方法的子类也必须重写该方法)
---->解决方法:接口
1、接口是抽象类的延伸,可看作纯粹的抽象类。
2、接口中所有方法都没有方法体。
3、可将上述(一部分子类需要一部分不需要的)方法封装到一个接口中,使需要这些方法的那一部分类实现该接口,同时所有类都继承父类抽象类。
4、接口使用interface关键字进行定义:
public interface drawTest{
void draw(); //接口内的方法,省略abstract关键字
}
5、一个类实现一个接口可以使用implements关键字:
public class 子类名 extends 父类抽象类名 implements 接口名{
……//
}
6、在接口中定义的方法必须被定义为 public 或 abstract 形式,其他修饰权限不被java编译器认可。即使不将该方法声明为public形式,它也是public。
7、在接口中定义的任何字段都自动是 static 和 final 的。
Java中不允许多重继承,即不允许一个子类同时继承一个或多个父类(即同时extends多个类)。
实现方法:使用接口可以实现多重继承(即可以同时implements多个接口,同时实现多个接口)。
多重继承语法:
class 类名 implements 接口1,接口2,...,接口n
在定义一个接口时使该接口继承另外一个接口:
interface intf1{
...//
}
interface intf2 extends intf1{
...//
}
1、一个类只能继承一个类:class A extends B{}
2、一个类可以实现多个接口:class A implements B,C,...{}
3、一个接口可以继承多个接口:interface intf1 extends intf2,intf3,...{}
4、在继承类的同时也可以继承接口:class A extends B implements intf1,intf2,...{}
这就是选择用接口而不选择抽象类的原因。
(具体代码示例:)
interface drawTest{ //定义接口
public void draw(); //定义方法,没有方法体
}
class ParallelogramgleUseInterface extends QuadrangleUseInterface implements drawTest{
public void draw() { //因为该类实现了接口,所以需要覆盖draw()方法
System.out.println("平行四边形.draw()");
}
public void doAnything() { //覆盖父类方法
//……
}
}
class SquareUseInterface extends QuadrangleUseInterface implements drawTest{
public void draw() {
System.out.println("正方形.draw()");
}
public void doAnything() {
//……
}
}
public class QuadrangleUseInterface {
public void doAnything() {
//……
}
public static void main(String[] args) {
//接口也可以进行向上转型操作
drawTest[] d = {new SquareUseInterface(), new ParallelogramgleUseInterface()};
for(int i=0;i