黑马程序员 第七篇 继承 (part 1) (Foundation; completed)
2015-08-01 15:47
666 查看
——- android培训、java培训、期待与您交流! ———-
目录
1.什么是继承
2.修饰符
3.成员变量的覆盖
4.对象引用
5.方法的重写和重载
日常生活中,我们常遇到类似自行车和公路赛车的问题
自行车有颜色大小之分,公路赛车同样也有颜色大小之分,也多了一项特殊属性即速度的优势;自行车有的属性,公路车也有;公路车有的,自行车不一定有。
在Java中,遇到此类问题,可以通过继承来完成处理这类情况的功能。继承节省了定义新类中的大量工作,大大提高了代码的重用性。
代码解析:既然公路赛车是自行车的一种,我们可以用自行车类定义自行车,然后通过继承来使公路赛车获得自行车的所有属性,而公路赛车类只需要定义自己所特有的属性和状态。
就好比公路赛车是自行车的一个升级版本,很自然地拥有了自行车的特性。
通过继承来简化上面的程序
Java提供了单一继承,通过接口可以实现多重继承。
1.1 类的继承 (extends)
在Java中,被继承的类叫超类(super),继承超类的类叫做子类(subclass)。
因此,子类是超类的一个功能上的扩展,它继承了超类定义的所有属性和方法,并且添加了特有的功能方法。
所有的类都继承自Java.lang.Object类,所以说Object类是Java中所有类的父类。如果在定义的类中不做特殊的规定,自己定义的类均直接继承自Object类。
特性总结:
通过继承定义类,可以简化类的定义,让所需要的功能相应的子类去定义和实现
Java是单继承的,子类可以有很多,父类只能有一个。
Java的继承是多层继承,一个类可以有很多子类,而子类下面又可以有很多子类
父类里的属性和方法可以使子类同样拥有,而子类的不能调用父类的方法和属性,子类的午餐构造器默认是调用父类的无参构造器。
父类没有定义一个无参的构造器,那么编译器就默认生成一个午餐的构造器,也可以在子类构造器里显示使用super方法调用父类构造器,super方法里写几个参数就可以表示调用的是父类的哪一个构造器。
一般情况下,定义了一个有参的构造器,就应该定义一个无参的构造器
1.2 继承的语法
语法
修饰成员变量的修饰符主要有4个 public private default protected
2、final修饰符
final的意思是不可变,他可以修饰类、字段、方法。修饰类后类不能被扩展(extends),也就是不能被继承。修饰字段后字段的值不能被改变,因此如果有final修饰字段,应该对字段进行手动初始化。修饰方法后该方法不能被改变,也就是重写。
3、abstract修饰符
abstract是抽象的意思,用来修饰类和方法,修饰类后,该类为抽象类,不能被实例化,必需进行扩展。修饰方法后,该方法为抽象方法必须被子类重写(override)。
4、static修饰符
static用来修饰内部类,方法,字段。修饰内部类说明该内部类属于外部类而不属于外部类的某个实例。修饰字段说明该字段属于类而不属于类实例。修饰方法说明该方法属于类而不属于类实例。
详细参考
Java修饰符全解:
http://www.cnblogs.com/leokou/archive/2011/06/30/2094282.html
静态方法无法重写
所有getFruitColor 返回蓝色
getFruitSize被重写返回小
创建了一个Human类的对象aPerson。
上面是一个非常简单的表述,但我们有许多细节需要深入:
首先看等号的右侧。new是在内存中为对象开辟空间。具体来说,new是在内存的堆(heap)上为对象开辟空间。这一空间中,保存有对象的数据和方法。
再看等号的左侧。aPerson指代一个Human对象,被称为对象引用(reference)。实际上,aPerson并不是对象本身,而是类似于一个指向对象的指针。aPerson存在于内存的栈(stack)中。
当我们用等号赋值时,是将右侧new在堆中创建对象的地址赋予给对象引用。
这里的内存,指的是JVM (Java Virtual Machine)虚拟出来的Java进程内存空间。内存的堆和栈概念可参考Linux从程序到进程。
参考资料
作者:Vamei 出处:http://www.cnblogs.com/vamei
对象引用
http://www.cnblogs.com/vamei/archive/2013/04/01/2992484.html
静态方法不可重写。
关于自行车和公路赛车的相同点和不同点例子
问题 如果把
Java里重载的关键字为overload。
重载的方法名称相同,但方法的参数列表不同。如参数个数和参数类型等。
重载的方法和返回值可以相同也可以不相同。
示例代码如下
代码说明:
虽然3种方法的名称是相同的,但这3种方法的参数列表,即个数和类型,是不相同的。
判断方法是否重载,看参数列别是很重要的。
一个重载的例子
如果返回类型是对象引用类型,重写的方法返回类型可以相同,也可以派生(父类的派生类,即子类)自被重写方法的返回类型。
以下演示一段错误的使用返回类型的代码
下面代码演示来说明静态方法不能被重写
Son m = new Son()
math m = new math()
调用door的getMes()方法
因为编译期为math类型,又因为getMes方法被修饰为static类型的。所以对象引用m在运行期被强制转型为math类型
public boolean equals(Object obj)
{
return (this == obj); //这里比较的是两个对象的引用
}
public class EqualTest {
public static void main(String[] args) {
//因为对象变量的存储的是对象在内存中的路径,即内存地址。所以用“==”比较时,即使
//对象的值相等,但是他们的内存地址不同,所以==的结果为false。故“==”用于比较两
//个变量的值是否相等,而不是变量引用的对象是否相等
//equal用于比较两个对象是否相同。
}
}
“`
—–【(t1+t2)=t3】true
—–【t3=t4】true
—–【i1.equals(i2)】false
—–【i3.equals(i1+i2)】true
—–【i3.equals(i4)】true
—–【st1==st2】false
—–【(st1+st2)==st3】false
—–【st3==st4】true
—–【st1.equals(st2)】false
—–【(st1+st2).equals(st3)】true
—–【st3.equals(st4)】true
总之:
**“==”比较的是值【变量(栈)内存中存放的对象的(堆)内存地址】
equal用于比较两个对象的值是否相同【不是比地址】**
【特别注意】Object类中的equals方法和“==”是一样的,没有区别,而String类,Integer类等等一些类,是重写了equals方法,才使得equals和“==不同”,所以,当自己创建类时,自动继承了Object的equals方法,要想实现不同的等于比较,必须重写equals方法。
“==”比”equal”运行速度快,因为”==”只是比较引用.
reference:
http://blog.csdn.net/xcysuccess3/article/details/6557771
——- android培训、java培训、期待与您交流! ———-
目录
1.什么是继承
2.修饰符
3.成员变量的覆盖
4.对象引用
5.方法的重写和重载
1.什么是继承
Java提供了单一继承,通过接口可以实现多重继承。日常生活中,我们常遇到类似自行车和公路赛车的问题
自行车有颜色大小之分,公路赛车同样也有颜色大小之分,也多了一项特殊属性即速度的优势;自行车有的属性,公路车也有;公路车有的,自行车不一定有。
在Java中,遇到此类问题,可以通过继承来完成处理这类情况的功能。继承节省了定义新类中的大量工作,大大提高了代码的重用性。
//创建一个自行车类 public class bike { public Sstring color' public int size; } //创建一个公路车赛车类 public class racing_cycle { public String color; public int size; public String speed; }
代码解析:既然公路赛车是自行车的一种,我们可以用自行车类定义自行车,然后通过继承来使公路赛车获得自行车的所有属性,而公路赛车类只需要定义自己所特有的属性和状态。
就好比公路赛车是自行车的一个升级版本,很自然地拥有了自行车的特性。
通过继承来简化上面的程序
public class bike { public String color; public int size; } public class racing_cycle extends bike { public String speed; }
Java提供了单一继承,通过接口可以实现多重继承。
1.1 类的继承 (extends)
在Java中,被继承的类叫超类(super),继承超类的类叫做子类(subclass)。
因此,子类是超类的一个功能上的扩展,它继承了超类定义的所有属性和方法,并且添加了特有的功能方法。
所有的类都继承自Java.lang.Object类,所以说Object类是Java中所有类的父类。如果在定义的类中不做特殊的规定,自己定义的类均直接继承自Object类。
特性总结:
通过继承定义类,可以简化类的定义,让所需要的功能相应的子类去定义和实现
Java是单继承的,子类可以有很多,父类只能有一个。
Java的继承是多层继承,一个类可以有很多子类,而子类下面又可以有很多子类
父类里的属性和方法可以使子类同样拥有,而子类的不能调用父类的方法和属性,子类的午餐构造器默认是调用父类的无参构造器。
父类没有定义一个无参的构造器,那么编译器就默认生成一个午餐的构造器,也可以在子类构造器里显示使用super方法调用父类构造器,super方法里写几个参数就可以表示调用的是父类的哪一个构造器。
一般情况下,定义了一个有参的构造器,就应该定义一个无参的构造器
1.2 继承的语法
语法
class 类名 extends 父类名称
2.修饰符
在定义类的一个成员变量和方法时,必须要指定成员变量或方法的访问权限,这时就需要使用到修饰符。修饰符是修饰的当前成员变量的访问限制和状态的。Java中的修饰符主要有public,protected,private,static和final。修饰成员变量的修饰符主要有4个 public private default protected
2、final修饰符
final的意思是不可变,他可以修饰类、字段、方法。修饰类后类不能被扩展(extends),也就是不能被继承。修饰字段后字段的值不能被改变,因此如果有final修饰字段,应该对字段进行手动初始化。修饰方法后该方法不能被改变,也就是重写。
3、abstract修饰符
abstract是抽象的意思,用来修饰类和方法,修饰类后,该类为抽象类,不能被实例化,必需进行扩展。修饰方法后,该方法为抽象方法必须被子类重写(override)。
4、static修饰符
static用来修饰内部类,方法,字段。修饰内部类说明该内部类属于外部类而不属于外部类的某个实例。修饰字段说明该字段属于类而不属于类实例。修饰方法说明该方法属于类而不属于类实例。
详细参考
Java修饰符全解:
http://www.cnblogs.com/leokou/archive/2011/06/30/2094282.html
3.成员变量的覆盖
class fruit { static String color = "蓝色"; String size = "大"; static String getFruirColor() { return color; } String getFruitSize() { return size; } } public class apple extends fruit { static String appleColor = "红色"; String appleSize = "小"; static String getFruitColor() { return appleColor; } String getFruitSize(); { return appleSize; } public static void main(String[] args) { fruit f = new apple(); System.out.println(f.getFruitColor()); System.out.println(f.getFruitSize()); } } 输出结果 打印 蓝色 小
静态方法无法重写
所有getFruitColor 返回蓝色
getFruitSize被重写返回小
4.对象引用
外部可以调用类来创建对象,比如上面在Test类中:Human aPerson = new Human(160);
创建了一个Human类的对象aPerson。
上面是一个非常简单的表述,但我们有许多细节需要深入:
首先看等号的右侧。new是在内存中为对象开辟空间。具体来说,new是在内存的堆(heap)上为对象开辟空间。这一空间中,保存有对象的数据和方法。
再看等号的左侧。aPerson指代一个Human对象,被称为对象引用(reference)。实际上,aPerson并不是对象本身,而是类似于一个指向对象的指针。aPerson存在于内存的栈(stack)中。
当我们用等号赋值时,是将右侧new在堆中创建对象的地址赋予给对象引用。
这里的内存,指的是JVM (Java Virtual Machine)虚拟出来的Java进程内存空间。内存的堆和栈概念可参考Linux从程序到进程。
参考资料
作者:Vamei 出处:http://www.cnblogs.com/vamei
对象引用
http://www.cnblogs.com/vamei/archive/2013/04/01/2992484.html
5.方法的重写和重载
5.1 方法重写的特点 5.2 方法重载的特点 5.3 重写的返回类型 5.4 重写是基于继承的 5.5 静态方法是不能重写的 5.6 三者之间的关系 5.7 重写toString方法
5.1 方法重写的特点
方法重写也可以叫方法的覆盖,关键词为override。在子类本身的方法中,如果和所继承的方法具有相同的名称,便构成了方法的重写。重写的特点就是能够为各个子类定义特有行为。静态方法不可重写。
关于自行车和公路赛车的相同点和不同点例子
class bike { public void move() { System.out.println("速度慢的!"); } public class racing_cycle extends bike { public void move() { System.out.println("速度快的!"); } public static void main(String[] args) { racing_cycle rc = new racing_cycle(); rc.move(); } } 输出结果 打印 速度快的!
问题 如果把
racing_cycle rc = new racing_cycle(); 换成 bike rc = new racing_cycle();
5.2 方法重载的特点
方法的重载就是指在一个类中,存在两个或者两个以上具有相同名称,不同参数的方法。Java里重载的关键字为overload。
重载的方法名称相同,但方法的参数列表不同。如参数个数和参数类型等。
重载的方法和返回值可以相同也可以不相同。
示例代码如下
public String move() {} public String move(String name) {} public void move(String name, int spend) {}
代码说明:
虽然3种方法的名称是相同的,但这3种方法的参数列表,即个数和类型,是不相同的。
判断方法是否重载,看参数列别是很重要的。
一个重载的例子
class math { public int add(int i, int j) { return i+j; } public float add(float i, float j) { return i+j; } public static void main(String args[]) { math m = new math(); System.out.println(m.add(1.0f, 2.3f)); System.out.println(m.add(1, 2)); } } 输出结果: 打印 3.3 3
5.3 重写的返回类型
方法有它的返回类型,而重写的方法也有返回类型,并有一些相应的限制。方法被重写后,返回的类型为基本类型时,重写方法的返回要必须一样,否则会出现错误。如果返回类型是对象引用类型,重写的方法返回类型可以相同,也可以派生(父类的派生类,即子类)自被重写方法的返回类型。
以下演示一段错误的使用返回类型的代码
class math { public int add() { return 10 + 15; } } public class son extends math { public float add() { return 10 + 15; } public static void main(String[] args) { math m = new son(); System.out.println(m.add()); } } 运行结果: 代码编译不通过 因为该代码重写add() 但返回类型改变了,所以出错。
5.4 重写是基于继承的
重写和重载的产生是基于继承,如果没有发生继承就不会产生重写和重载了。在实际开发中,一定要注意继承是重写的基础,没有继承就不会存在重写。class door { ] class wood_Door extends door { } class math { static public door getMes() { return new door(); } } public class Son extends math { static public wood_Door getMes() { return new wood_Door(); } public static void main(String[] args) { math m = new Son(); System.out.println(m.getMes()); } } 输出结果: door@61de33 代码解析 父类和子类的getMes是被修饰为static类型的,static关键字表示这个方法为静态方法,具有唯一性,是个类方法。因为static类型的方法不能被重写,所以方法m.getMes() 调用的是父类的方法`getMes(){return new door();}`
5.5 静态方法是不能重写的
静态方法就是被修饰为static类型的方法,在类里声明具有唯一性,不是通过类的实例化而存在的,而是通过类的建立而存在,可以理解为用关键字new创建对象了,就是把这个对象实例化了。Java中的静态方法可以被继承,但是不可以被重写。下面代码演示来说明静态方法不能被重写
class door { } class wood_Door extends door { } class math { static public door getMes() { return new door(); } } public class Son extends math { static public wood_Door getMes() { return new wood_Door(); ] public static void main(String[] args) { Son m = new Son(); System.out.println(m.getMes()); } } 输出结果 打印 wood_Door@61de33 这里调用了wood_Door的getMes()方法,因为创建对象的时候使
Son m = new Son()
区别于上一段代码的
math m = new math()
调用door的getMes()方法
因为编译期为math类型,又因为getMes方法被修饰为static类型的。所以对象引用m在运行期被强制转型为math类型
总结 == - 父类的静态方法可以被子类的静态方法覆盖 - 父类的非静态方法不能被子类的静态方法覆盖 - 父类的静态方法不能被子类的非静态方法覆盖 - 覆盖用于父类和子类之间 - 重写用在同一个类中,有相同的方法名,但参数不一样。 5.6 三者之间的关系 ----------- 重写关键字是override,重载的关键字为overload,重写,重载,覆盖,都是基于继承的关系。当继承的关系放了,想用父类的方法就用super关键词来引用,如果想用新的方法了就重写,来完成新的功能需要。 对覆盖(重写也叫覆盖)的总结: --------------- - 覆盖的方法的参数列表必须要和被覆盖的方法的参数列表完全相同,才能达到覆盖的效果 - 覆盖的方法的返回值必须和被覆盖的方法的返回值一致 - 覆盖的方法锁抛出的异常必须和被覆盖的方法所抛出的异常一致,或者是其子类 - 被覆盖的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。 ## 对重载的总结: ## - 使用重载时只能定义不同的参数列表 - 不能通过重载的方法对返回类型,访问权限和抛出的异常来进行方法的重载 重写的总结如下 ------- - 重写的方法存在于父类中,也存在于子类中 - 重写的方法在运行期采用多态的形式 - 重写的方法不能比被重写的方法有更高的访问权限 - 重写的方法不能比被重写的方法有更多的异常 5.7 重写toString方法 ---------------- toString方法是Java里Object类的方法,很多类都重写了该方法。该方法返回对象的状态信息。如果需要得到比较详细的状态信息,就需要对toString方法进行重写。 5.8 重写equals ------------ 方法equals也是Object类的方法,很多类也进行了重写,一般重写equals方法是为了比较两个对象的内容是否相等。equals方法在两个比较的对象指向同一个对象的时候才会返回真值。如果需要进行比较详细的判断,就需要对equals方法进行重写。 equals的原型
public boolean equals(Object obj)
{
return (this == obj); //这里比较的是两个对象的引用
}
关于equals和==的区别总结 ================
public class EqualTest {
public static void main(String[] args) {
//对于基本类型的变量。"=="和"equal"的区别 int t1=57; int t2=67; int t3=124; int t4=124; //“==”对于基本数据类型,判断两个变量的值是否相等。 Boolean result1=(t1==t2); Boolean result2=((t1+t2)==t3); Boolean result3=(t3==t4); System.out.println("/n/n-----【t1==t2】"+result1+"/n-----【(t1+t2)=t3】"+result2+"/n-----【t3=t4】"+result3); //“equal”不能用于基本数据类型。只能用于类变量。对于基本数据类型要用其包装类。 Integer i1=new Integer(t1); Integer i2=new Integer(t2); Integer i3=new Integer(t3); Integer i4=new Integer(t4); Boolean ri1=i1.equals(i2); Boolean ri2=i3.equals(i1+i2); Boolean ri3=i3.equals(i4); System.out.println("/n/n-----【i1.equals(i2)】"+ri1+"/n-----【i3.equals(i1+i2)】"+ri2+"/n-----【i3.equals(i4)】"+ri3); //对于对象变量,"=="和"equal"的区别 String st1="wasiker "; String st2="is super man"; String st3="wasiker is super man"; String st4="wasiker is super man"; Boolean b1=(st1==st2); Boolean b2=(st1+st2)==st3; Boolean b3=(st3==st4); System.out.println("/n/n-----【st1==st2】"+b1+"/n-----【(st1+st2)==st3】"+b2+"/n-----【st3==st4】"+b3);
//因为对象变量的存储的是对象在内存中的路径,即内存地址。所以用“==”比较时,即使
//对象的值相等,但是他们的内存地址不同,所以==的结果为false。故“==”用于比较两
//个变量的值是否相等,而不是变量引用的对象是否相等
Boolean r1=st1.equals(st2); Boolean r2=(st1+st2).equals(st3); Boolean r3=st3.equals(st4); System.out.println("/n/n-----【st1.equals(st2)】"+r1+"/n-----【(st1+st2).equals(st3)】"+r2+"/n-----【st3.equals(st4)】"+r3);
//equal用于比较两个对象是否相同。
}
}
“`
运行结果为:
—–【t1==t2】false—–【(t1+t2)=t3】true
—–【t3=t4】true
—–【i1.equals(i2)】false
—–【i3.equals(i1+i2)】true
—–【i3.equals(i4)】true
—–【st1==st2】false
—–【(st1+st2)==st3】false
—–【st3==st4】true
—–【st1.equals(st2)】false
—–【(st1+st2).equals(st3)】true
—–【st3.equals(st4)】true
总之:
**“==”比较的是值【变量(栈)内存中存放的对象的(堆)内存地址】
equal用于比较两个对象的值是否相同【不是比地址】**
【特别注意】Object类中的equals方法和“==”是一样的,没有区别,而String类,Integer类等等一些类,是重写了equals方法,才使得equals和“==不同”,所以,当自己创建类时,自动继承了Object的equals方法,要想实现不同的等于比较,必须重写equals方法。
“==”比”equal”运行速度快,因为”==”只是比较引用.
reference:
http://blog.csdn.net/xcysuccess3/article/details/6557771
——- android培训、java培训、期待与您交流! ———-
相关文章推荐
- 【练习笔记】剑指offer-面试题7 :用两个栈实现队列
- 面试常考点:虚假唤醒 Spurious wakeup
- 黑马程序员——15,String,StringBuffer,基本数据类型包装对象
- 剑指Offer面试题15(Java版):链表中倒数第K个结点
- 黑马程序员—— 反射总结
- 【剑指Offer面试题】 九度OJ1523:从上往下打印二叉树
- 黑马程序员——java学习9(毕15-16)——TreeSet、Map、泛型、字符排序
- 怎样才是理想的程序员
- 黑马程序员——多线程知识总结1
- 【练习笔记】剑指offer-面试题6 :重建二义树
- 黑马程序员------TreeSet集合框架存储自定义元素之排序Comparable与Comparator
- 黑马程序员-------集合框架之Collection
- 程序员必读书单
- 剑指offer面试题14(Java版):调整数组顺序使奇数位于偶数的前面
- 【练习笔记】剑指offer-面试题5 :从尾到头打印链表
- 黑马程序员——字符串常见操作
- 每个程序员和设计师必做的10项运动
- 黑马程序员——OC类方法
- 【练习笔记】剑指offer-面试题4 :替换空格
- 面试30 求数组中最小的k个数