Java基础---类的继承
来源:互联网 发布:淘宝卖家充快递单号 编辑:程序博客网 时间:2024/05/22 06:12
在Java中,被继承的类叫超类(superclass),继承超类的类叫子类(subclass)。子类继承了超类中所有的属性和方法。
有一对爷俩,爸爸和儿子,爸爸的眼睛是单眼皮,个子很高,头发很好,皮肤很黑,而儿子同样有他爸爸的一些特征,但是儿子的皮肤很白,双眼皮,戴眼镜,在外人看来他们是爷俩。儿子具有爸爸的所有特征,但是儿子的皮肤很白和戴眼睛这些是儿子自己所特有的,也是和爸爸不一样的地方。这个小例子正是日常生活里常见的。
换到Java里,类与类之间的关系,可以看成倒置的金字塔,爸爸在上面,儿子在下面。爸爸可能有多个儿子,但是一个儿子只能有一个爸爸,这在日常生活里也是如此。
换到Java里,类与类之间的关系,可以看成倒置的金字塔,爸爸在上面,儿子在下面。爸爸可能有多个儿子,但是一个儿子只能有一个爸爸,这在日常生活里也是如此。
示例:
class Test {public Test(){ //构造方法}protected void doSomething(){ //成员方法}protected Test doIt(){//方法返回值类型为Test类型return new Test();}}class Test2 extends Test //继承父类{public Test2(){ //构造方法super(); //调用父类构造方法super.doSomething();//调用父类成员方法}public void doSomethingnew(){ //新增方法}public void doSomething(){ //重写父类方法}protected Test2 doIt2(){ //重写父类方法return new Test2();}}注意:一个超类可以有多个子类,但是一个子类却只能有一个父类。(这点和C语言不同,java是通过接口来实现多继承的,这样可以避免方法重复时一系列的问题)
关于继承时的覆盖有几点需要注意的:
1.构造函数:
当子类继承父类时,构造子类时会调用父类的构造函数,有三种情况:
(1)父类无构造函数或者一个无参数构造函数,子类若无构造函数或者有无参数构造函数,子类构造函数中不需要显式调用父类的构造函数,系统会自动在调用子类构造函数前调用父类的构造函数
(2)父类只有有参数构造函数,子类在构造方法中必须要显示调用父类的构造函数,否则编译出错
(3)父类既有无参数构造函数,也有有参构造函数,子类可以不在构造方法中调用父类的构造函数,这时使用的是父类的无参数构造函数
(2)父类只有有参数构造函数,子类在构造方法中必须要显示调用父类的构造函数,否则编译出错
(3)父类既有无参数构造函数,也有有参构造函数,子类可以不在构造方法中调用父类的构造函数,这时使用的是父类的无参数构造函数
2.方法
(1)子类覆盖父类的方法,必须有同样的参数返回类型,否则编译不能通过
(2)子类覆盖父类的方法,在jdk1.5后,参数返回类可以是父类方法返回类的子类
(3)子类覆盖父类方法,可以修改方法作用域修饰符,但只能把方法的作用域放大,而不能把public修改为private
(4)子类方法能够访问父类的protected作用域成员,不能够访问默认的作用域成员
(5)子类的静态方法不能隐藏同名的父类实例方法
(6)java与C++一样,继承的方法具有多态性
(2)子类覆盖父类的方法,在jdk1.5后,参数返回类可以是父类方法返回类的子类
(3)子类覆盖父类方法,可以修改方法作用域修饰符,但只能把方法的作用域放大,而不能把public修改为private
(4)子类方法能够访问父类的protected作用域成员,不能够访问默认的作用域成员
(5)子类的静态方法不能隐藏同名的父类实例方法
(6)java与C++一样,继承的方法具有多态性
3.成员
成员比较简单,子类覆盖父类成员时,各自的方法中调用的是各自方法中的成员变量
那么什么时候需要使用覆盖呢?
当子类需要父类的功能,而且子类在该功能的基础上增加一些自己的特点。示例:
class Phone6 {void call(){}void show(){System.out.println("number");}}class Phone6s extends Phone6 {void show(){System.out.println("name");System.out.println("address"); //子类新增的功能super.show(); //调用父类方法功能}}class ExtendDemo{public static void main(String[] args){Phone6s p = new Phone6s(); //创建子类p.show(); //调用子类方法}}注意:父类中的私有方法和static方法不能被覆盖,而且覆盖时子类的权限要大于或者等于父类的的权限。
还有,类加载器在加载子类时,会先加载父类,也就是会先初始化父类,并且子类会执行父类的构造方法。
再说个有关继承的关键字:final
因为继承有个不好的地方,就是打破了java的封装性,你想继承什么类就继承什么类怎么行呢? 于是就出现了final关键字。
它的作用有: 可以修饰类,方法,变量。 被修饰的类不能被继承,被修饰的方法不能被覆盖,被修饰的变量就成了常量。也就是被它修饰的东西就是最终端。
抽象类:
抽象类定义:顾名思义,就是抽象的类。 没有方法的方法体是抽象方法,包含抽象方法的类就是抽象类。
抽象类的特点:它有自己特有的修饰,用abstract来修饰。它只是声明了方法,却没有具体的方法体。
因为没有方法体所以不能被实例化,那么有什么用呢? 可以通过继承,覆盖里面抽象的方法,就行了。
抽象类和一般类的区别:
1.一般类不能定义抽象方法,可以定义非抽象方法,抽象类可以定义抽象方法,也可以定义非抽象方法。
2.一般类可以实例化,抽象不能被实例化。
因为程序员和经理都是雇员,存在着一些一样的特征。进行抽取。
//描述雇员。abstract class Employee{ private String name ; private String id ; private double pay ; Employee(String name,String id, double pay){ this.name = name; this.id = id; this.pay = pay; } public abstract void work(); }//描述程序员class Programmer extends Employee{ //继承雇员 Programmer(String name,String id, double pay){ super(name,id,pay); } public void work(){ //实例化抽象方法 System.out.println("code..." ); }}//描述经理class Manager extends Employee{ //继承雇员 private int bonus ; Manager(String name,String id, double pay,int bonus){ super(name,id,pay); this.bonus = bonus; } public void work(){//实例化抽象方法 System.out.println("manage" ); }}
接口:
理解了抽象类之后理解接口就简单了。 接口就是非常抽象的抽象类。也就是当抽象类中的方法都是抽象的时候,它就成了接口。
格式:interface{}
由于接口是完全抽象的,所以它和抽象类一样,不能被直接实例化。也需要被别的类实现。而且当它被别的类重写时,所有的方法由于都是抽象的,因而必须所有方法都重写,否则一样不能被实例化。因为只要有抽象方法存在,那个类就是个抽象类。
接口不是类。 类和类之间是继承关系,类和接口之间是实现关系。 之间说过继承只能但继承,因为有可能方法重复而带来一系列问题。 类却可以实现多个接口却不会有什么问题,因为接口的方法都是抽象的,即使有重名的方法,当你实现它的时候你也需要去重写定义它,就不存在多继承时出现的问题。 接口的出现避免了但继承的局限性。 这样一个类在继承一个类的同时,还是实现多个接口。
示例:
interface A{public void show();}interface B{public void show();}abstract class C{public void method(){}}class D extends C implements A,B{public void show(){System.out.println("Ashow");}public void method(){System.out.println("Cmethod");}}class interfaceDemo{public static void main(String[] args){D d = new D();d.show();d.method();}}
多态:
某一类事物的多种存在形态。
父类或者接口的引用指向或者接收自己的子类对象,好处是提高了程序的扩展性。
成员变量
编译时:参考因引用型变量所属的类中是否有调用的成员变量,没有就不能通过
成员函数
编译看左边,运行看右边
静态函数
编译和运行都取决于左边
abstract class Animal{ abstract void eat();}//狗猫猪都继承了抽象类动物类class Dog extends Animal{ void eat(){ System.out.println("啃骨头"); } void lookHome(){ System.out.println("看家"); }}class Cat extends Animal{ void eat(){ System.out.println("吃鱼"); } void catchMouse(){ System.out.println("抓老鼠"); }}class Pig extends Animal{ void eat(){ System.out.println("饲料"); } void gongdi(){ System.out.println("拱地"); }}class DuoTaiDemo{ public static void main(String[] args){ Cat c = new Cat(); Dog d = new Dog(); method(c);//向方法中传入cat对象,向上转型 method(d);//向上转型 method(new Pig()); } public static void method(Animal a){ a.eat(); }}
内部类:
内部类是在一个外部类的内部再定义一个类。类名不需要和文件夹相同
成员内部类:
作为外部类的成员,好处是可以直接调用外部类中的所有方法和成员,包括private。
注意:内部类中不能含有static的变量和方法,原因很简单,因为static优先存在,而内部类需要在外部类存在了才创建。
示例:
public class Outer{public static void main(String[] args){Outer outer = new Outer();Outer.Inner inner = outer.new Inner();//创建成员内部类对象inner.print("Outer.new"); //调用内部类的方法inner = outer.getInner(); inner.print("Outer.get");//调用外部类的成员方法}public Inner getInner(){return new Inner();}public class Inner //成员内部类{public void print(String str)//内部类的方法{System.out.println(str);}}}运行结果:
局部内部类:
是定义在方法和作用域的内部类
class Outer{int num = 3;void method(final int y){final int x = 9;//被final修饰的变量不会改值class Inner //定义在成员方法内部的内部类{void show(){System.out.println("show..."+x+","+y);}}Inner in = new Inner();//创建了方法内部的内部类in.show();//调用内部类的方法}}class InnerClassDemo{public static void main(String[] args){new Outer().method(4); //实现并调用类中的方法}}
show...9,4
匿名内部类:
如果满足下面的一些条件,使用匿名内部类是比较合适的:
1.只用到类的一个实例
2.类在定义后马上用到
3.类非常小,最好在4行代码以内
4.给类命名并不会导致你的代码更容易理解
注意:
1.匿名内部类不能有构造方法
2.匿名内部类不能定义任何静态成员,方法,类
3.匿名内部类不能是public protected private static
4.只能创建匿名内部类的一个实例
5.一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类
public class AnnInnerClassDemo{public static void main(String[] args){Demo demo = new Demo(){};//匿名内部类}}class Demo{}{}为类体,只有类体,没有类名
class AnnInnerClassDemo2{public static void main(String[] args){/*1.匿名内部类new Demo(){}是对Demo的继承, 并同时实例化 new Demo(){}是Demo子类实例,是一个对象 2.类体中可以声明大部分类的功能,比如覆盖的toString()方法 */Demo2 demo = new Demo2(){};//匿名内部类Demo2 demo1 = new Demo2(){public String toString(){return "i am demo1";}};System.out.println(demo);System.out.println(demo1);}}class Demo2{}
0 0
- java 基础 类的继承
- Java基础---类的继承
- java 继承的基础
- java继承的基础
- 基础的Java继承
- java基础_day0021_类的继承_
- java基础学习(四)java类的继承
- java-基础-类与继承
- Java基础10 接口的继承与抽象类
- Java基础学习之——类的继承extends
- JAVA入门基础文章3-类的概念-什么是继承
- 黑马程序员-java基础-继承中类的初始化顺序
- Java基础10 接口的继承与抽象类
- Java基础10 接口的继承与抽象类
- Java基础10 接口的继承与抽象类
- Java基础——接口的继承与抽象类
- JAVA基础篇 ,类 对象,,封装 , 继承 的抽象思想
- java基础-类元素的初始化与继承多态
- 【iOS】【FMDB】【sqlite】try catch实现事务处理
- hive错误集锦
- GeoServer的SQL Views详解
- 处理注解@RequestParam的"Required String parameter is not present" 此博文包含图片
- 【安卓】Android API 指南之数据存储(Data Storage)之存储选项(Storage Options)
- Java基础---类的继承
- [LeetCode154]Find Minimum in Rotated Sorted Array II
- Android:BLE(Bluetooth Low Energy)开发
- 未定义的类型
- 万能的分页类
- 图片存到本地
- java.lang.UnsupportedClassVersionError 解决办法
- 测试博客第一篇
- Android SDK Timer的schedule()方法的正确使用