含义
- 实现了共同属性和行为的复用(对子类提取共性)
- 继承使类和类之间产生了关系,被继承的类称为父类,继承的类称为子类
特点
java中的继承:
- 单继承:一个类只能有一个父类(当有多个父类时,会存在调用的不确定性问题)
- 多层继承
super
- 代表父类的数据空间
- 当子类和父类中出现同名现象时,用来进行区分的
class Fu{
int age=5;
}
class Zi extends Fu{
int age=6;
public void show(){
System.out.println(super.age);//5
System.out.println(age);//6
}
}
继承private
- 私有的被子类继承了,只是子类无权限使用
class Fu{
int age=5;
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
}
class Zi extends Fu{
public void show(){
//System.out.println(age);//6
setAge(18);
System.out.println(getAge());
}
}
重写
- 子类在继承父类时,出现了一个或多个父类中相同的方法(返回值、方法名、参数),这种现象叫重写,也叫覆盖。
- 创建子类对象调用重写的方法,执行的肯定是重写之后的方法。
- 子类和父类有共同的行为,只是子类对该行为的表现方式不同,java认为子类没必要再定义一个新的方法。直接定义一个和父类相同的方法,改变方法的实现方式。
注意
-
子类在重写父类中方法时,重写的方法前边的访问权限必须大于等于父类中被重写方法的访问权限。
-
private不能被重写
-
如果父类方法的返回值类型是引用类型,那么子类在重写该方法时,返回值类型可以是父类方法返回值类型的子类类型;
如果父类方法的返回值类型是基本类型,那么子类在重写该方法时,返回值类型必须和父类方法的返回值类型保持一致
class ZhangSan
{
public void eat()
{
System.out.println("细嚼慢咽的吃");
}
}
class ZhangXiaoSan extends ZhangSan
{
public void eat(){
super.eat();
System.out.println("狼吞虎咽的吃");
}
}
构造方法中的继承
-
在创建子类对象时,先执行父类的构造方法,再执行子类的构造方法
-
原因是系统自动在子类的构造方法的第一行加入了一行代码
super();
-
super()
的含义是调用父类的空参的构造函数 -
为什么要先执行父类的构造函数:子类继承父类,必然要继承父类中的属性
可以利用父类中的构造函数给属性赋值class Person { Person(){ System.out.println("父类"); } Person(int age, String name){ this.age=age; this.name=name; } class Worker extends Person { Worker(){ //super(); System.out.println("子类"); } Worker(int age, String name){ super(age,name);//super();必须写在第一行 } } class Demo1 { public static void main(String[] args){ Worker worker=new Worker(18,"小黑"); } }
-
this();
也必须加在第一行
this()
加在第一行后,super()
就加不进去了。但Person(int age)
中还有super()
,因此依然可以class Person extends Fu { int age; Person() { this(18);//super( ) } Person(int age) { //super(); this.age=age; } }
final
- 一个类被修饰为final,这个类不能有子类;
- 一个方法被修饰为final,这方法不能被重写;
- final修饰基本类型的成员变量,该变量为常量,只能赋值一次(error:无法为最终变量PI分配值)
- final修饰引用类型的成员变量,引用所指向的对象不能改变,始终指向一个对象;
- final修饰基本类型的局部变量,该变量的值不能被修改;
- final修饰引用类型的局部变量,引用所指向的对象不能改变,始终指向一个对象;
- final修饰形式参数,接收的值不能被修改。
//计算圆形面积
class Circle
{
private double radius;
public static final double PI=3.1415;
Circle(){}
Circle(double radius)
{
this.radius=radius;
}
public double getArea( )
{
return PI*radius*radius;
}
}
class Demo8
{
public static void main(String[] args)
{
Circle yuan=new Circle(5.6);
System.out.println(yuan.getArea());
}
}
abstract
- 对子类提取共性的过程中,子类对某一个或多个行为有不同的实现方式,父类无法确定该如何实现,则父类不实现(不加大括号)。这种没有实现的方法就叫抽象方法,需要被修饰为abstract,含有抽象方法的类就是抽象类,也要用abstract修饰。
- 抽象类不能创建对象,无法调用抽象方法,只能做父类。
- 一个类继承了抽象类,那么这个类中也有抽象方法,所以这个子类也是抽象类,只有子类重写了该抽象方法,才不是抽象类。
abstract class 犬科动物
{
public void 吃()
{
System.out.println("吃肉");
}
public abstract void 吼叫();//抽象方法:不写大括号,即没实现
}
class 狼
{
public void 吃()
{
System.out.println("吃肉");
}
public void 吼叫()
{
System.out.println("嗷嗷叫");
}
}
class 狗
{
public void 吃()
{
System.out.println("吃肉");
}
public void 吼叫()
{
System.out.println("汪汪叫");
}
}
抽象类
- 抽象类是父类
- 抽象类有构造方法(创建子类对象,先要执行父类构造方法)
- 抽象类和普通类的区别
- 共同点:都是类
- 不同点:普通类可以创建对象,抽象类不能创建对象
- abstract不能和哪些关键字同时使用
- final:
- final修饰的类不能有子类
abstract修饰的类必须有子类 - final修饰的方法不能被重写
abstract修饰的方法必须能被重写
- final修饰的类不能有子类
- private:
- private修饰的方法不能被重写
abstract修饰的方法必须能被重写
- private修饰的方法不能被重写
- static:
- static修饰的方法可以直接使用类名访问
abstract修饰的方法不能使用类名访问
- static修饰的方法可以直接使用类名访问
- final:
- 抽象类不一定有抽象方法(当希望一个类不能创建对象时)
接口interface
- 看做特殊的类,编译后也是字节码文件(*.class)
- 接口是用来实现的,一个类可以实现多个接口,因为接口中的方法都是抽象方法,即使实现的多个接口中存在相同的方法,也不会出现调用的不确定性,因为在创建子类对象时,调用的肯定是重写之后的方法
- 从jdk1.8开始,接口中的方法也是可以实现的了(加上关键字default),所以当实现多个接口时,如果存在相同的已经实现的方法,会出现调用的不确定性。
interface 接口名
{
public static final 成员变量;//符号常量
public abstract 成员方法;//抽象变量
public default 成员方法;//实现方法
}
interface inter
{
public static final int NUM=66 ;
//public abstract void show();
public default void show()
{
System.out.println("show1");
}
}
interface inter2
{
//public abstract void show();
public default void show()
{
System.out.println("show2");
}
}
class Test implements inter, inter2
{
/*public void show( )
{
System.out.println("show");
}*/
}
class Demo12
{
public static void main(String[] args)
{
Test test=new Test();
System.out.println(inter.NUM);
System.out.println(Test.NUM);
System.out.println(test.NUM);
test.show();//调用不确定性
}
}
- 类和类之间是继承关系**(extends)**,通过继承可以得到共性的内容
- 类和接口之间是实现关系**(implements)**,通过实现可以得到继承所得不到的内容
- 接口是对单继承的一个补充
- 接口和接口之间是继承的关系
interface A{}
interface B extends A {}
interface C extends A,B {}
class Person {}
class Worker extends Person implements A,B,C{}