目录
1、继承的概念
2、方法的重写
3、重载和重写的区别
4、super关键字
5、this和super的区别
6、final关键字
7、抽象类
8、接口
1、继承的概念
在程序中,继承描述的是事物之间的所属关系,通过继承可以使很多事物之间形成一种关系体系。
在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类称为子类,现有类称为父类。子类继承父类的属性和方法,使子类对象实例具有父类的特征和行为。
在程序中,如果想声明一个类继承另一个类,需要使用extends关键字。
class 父类{
...
}
class 子类 extends 父类{
...
}
例如:Demo1对student的继承
public class student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Demo1 extends student{
public static void main(String[] args) {
Demo1 demo1=new Demo1();
demo1.setName("张三");
demo1.setAge(21);
System.out.println("姓名:"+demo1.getName()+" 年龄:"+demo1.getAge());
}
}
从上述代码可以看出,子类虽然没有任何的属性和方法,但是能调用父类的方法,这说明子类在继承父类的时候,会自动继承父类的成员。
在子类中也可以定义自己的属性和方法
例如:
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Demo1 extends Student {
private String sex;
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
class testDemo{
public static void main(String[] args) {
Demo1 demo1=new Demo1();
demo1.setName("张三");
demo1.setAge(21);
demo1.setSex("男");
System.out.println("姓名:"+demo1.getName()+" 年龄:"+demo1.getAge()+" 性别:"+demo1.getSex());
}
}
在类的继承中的注意事项:
1、在Java中,类只支持单继承,不允许多继承。
2、多个类可以继承同一个父类。
3、在Java中,可以进行多层继承。一个类的父类可以再继承另外的父类。
4、在Java中,子类和父类是一种相对的概念,一个类可以是某个类的父类,也可以是另一个类的子类。
2、方法的重写
在继承关系中,子类会自动继承父类中定义的方法,但有时子类需要对继承的方法进行一些修改,即对父类方法的重写。
在子类中重写的方法需要和父类被重写的方法具有相同的方法名、参数列表和返回值类型,且在子类重写的方法不能拥有比父类方法更加严格的访问修饰权限。
public class Student1 {
void shout(){
System.out.println("好好学习");
}
}
class Demo2 extends Student1{
@Override
void shout() {
System.out.println("天天向上");
}
public static void main(String[] args) {
Demo2 demo2=new Demo2();
demo2.shout();
}
}
编译后:
由此可以看出Demo2对象调用的是子类重写的shout()方法,而不是父类的shout()方法。
3、重载和重写的区别
1、定义及发生位置
重载
定义:重载发生在同一个类中,指的是在同一个类中允许存在多个方法,它们的方法名相同,但参数列表(参数的个数、类型或顺序)不同。
发生位置:重载发生在本类中
重写
定义:重写发生在父类与子类之间,子类重新定义了父类中已经存在的方法,即方法名、参数列表和返回值类型都相同,但方法体不同。
发生位置:重写发生在子类对父类方法的重新定义中。
2、参数列表及返回值类型
重载
参数列表:重载的方法参数列表必须不同,可以是参数个数不同,也可以是参数类型或顺序不同。
返回值类型:重载方法的返回值类型可以相同,也可以不同。
重写
参数列表:重写的方法参数列表必须完全相同。
返回值类型:重写方法的返回值类型必须与父类中被重写的方法一致。
3、访问修饰符及异常
重载
访问修饰符:重载方法的访问修饰符可以相同,也可以不同。
异常:重载方法抛出的异常可以不同,也可以不声明异常。
重写
访问修饰符:重写方法的访问修饰符不能比父类中被重写的方法的访问修饰符更低。
异常:重写方法不能抛出新的检查异常或比被重写方法声明更加宽泛的异常。
4、super关键字
当子类重写了父类的方法后,子类对象将无法访问父类被重写的方法,Java提供了super关键字,super关键字可以在子类中调用父类的普通属性、方法和构造方法。
1、使用super关键字访问父类的成员变量和成员方法
super.成员变量
super.成员方法(参数1,参数2...)
class Animal{
String name="哈士奇";
void shout(){
System.out.println("动物发出叫声");
}
}
class Dog extends Animal{
@Override
void shout() {
super.shout();
System.out.println("汪汪");
}
public void Name(){
System.out.println("名字:"+super.name);
}
}
public class Test {
public static void main(String[] args) {
Dog dog=new Dog();
dog.shout();
dog.Name();
}
}
执行结果:
动物发出叫声
汪汪
名字:哈士奇
调用了父类的方法shout()和父类的成员变量name()
2、使用super关键字访问父类中指定的构造方法
super(参数1,参数2...)
class Student{
private String name;
private int age;
//构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String print(){
return "姓名:"+this.getName()+" 年龄:"+this.getAge();
}
}
class Demo extends Student{
private String sex;
public Demo(String name,int age, String sex) {
//调用父类的构造方法
super(name,age);
this.sex = sex;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
//重写父类的方法
public String print() {
return super.print()+" 性别:"+this.sex;
}
}
public class TestDemo {
public static void main(String[] args) {
Demo demo=new Demo("张三",21,"男");
System.out.println(demo.print());
}
}
执行结果:
姓名:张三 年龄:21 性别:男
5、this和super的区别
区别点 | this | super |
属性访问 | 访问本类中的属性,如果本类没有, 则从父类中查找 | 直接访问父类中的属性 |
方法 | 访问本类中的方法,如果本类没有, 则从父类中查找 | 直接访问父类中的方法 |
调用构造 | 调用本类构造,必须放在构造方法的首行 | 调用父类构造,必须放在子类构造方法的首行 |
注意:this和super两者不可以同时出现,因为this和super在调用构造方法时都要求必须放在构造方法的首行。
6、final关键字
在Java中,可以使用final关键字声明类、属性、方法。
声明时注意事项:
1、使用final修饰的类不能有子类
2、使用final修饰的方法不能被子类重写
3、使用fianl修饰的变量(成员变量和局部变量)是常量,常量不可以修改
1、final关键字修饰类
Java中的类被final关键字修饰后,该类将不可以被继承。
2、final关键字修饰方法
3、final关键字修饰变量
Java中被final修饰的变量称为常量,常量只能在声明时可以被赋值,在后面的程序中,其值不能被改变,如果再次对该常量赋值,则程序会在编译时报错。
7、抽象类
当定义一个类时,需要定义一些成员方法来描述类的行为特征,但这些方法的实现方式是不同的。
例如:在定义Animal类时,shout()方法可以描述动物的叫声,但是不同动物的叫声是不同的,因此shout()方法中无法准确的描述动物的叫声。
针对这种情况,Java通过了抽象方法来满足这种需求。
抽象方法是使用abstract关键字来修饰成员方法,抽象方法在定义时不需要实现方法体。
定义格式如下:
abstract 返回值类型 方法名(参数);
当一个类包含了抽象方法,该类必须是抽象类。抽象类和抽象方法一样,都必须使用abstract关键字修饰。
定义格式如下:
abstract class 抽象类名称{
属性;
访问权限 返回值类型 方法名称(参数){ //普通方法
return [返回值];
}
访问权限 abstract 返回值类型 抽象方法名称(参数); //抽象方法,无方法体
}
抽象类的定义比普通方法多了一些抽象方法,其他部分组成基本相同。
抽象类定义的规则:
1、包含抽象方法的类,必须是抽象类
2、抽象类和抽象方法都需要使用abstract关键字声明
3、抽象类只需要声明,不需要实现
4、抽象类不可以被实例化
5、如果一个非抽象类继承了抽象类,那么该子类必须实现抽象类中的全部抽象方法。
例如:
abstract class Animal{
//定义抽象方法
abstract void shout();
}
class Dog extends Animal{
@Override
void shout() {
System.out.println("汪汪");
}
}
public class Example {
public static void main(String[] args) {
Dog dog=new Dog();
dog.shout();
}
}
执行结果:汪汪
注意:
使用abstract关键字修饰的抽象方法不能被private修饰,因为抽象方法必须被子类实现,如果使用了private声明,则子类无法实现该方法。
8、接口
如果一个抽象类的所有方法都是抽象的,则可以将这个类定义接口。接口中除了可以包括抽象方法外,还可以包含默认方法和静态方法,默认方法使用default修饰,静态方法使用static修饰,且这两个方法都允许有方法体。
接口使用interface关键字声明
public interface 接口名 extends 接口1 ,接口2...{
public static final 数据类型 常量名 =常量值;
public abstract 返回值类型 抽象方法名称(参数列表);
}
上述语法表示,一个接口可以有多个父接口,父接口之间用逗号分隔。
Java使用接口的目的是克服单继承的限制,因为一个类只能有一个父类,而一个接口可以同时继承多个父接口。
接口中的变量默认使用"public static final"修饰,即全局变量。接口中定义的方法默认使用"public abstract"进行修饰,即抽象方法。如果接口声明为public,则接口中的常量和方法全部为public。
接口中包含三类方法,抽象方法、默认方法和静态方法。静态方法可以通过“接口名.方法名”的形式来调用,而抽象方法和默认方法只能通过接口实现类的对象来调用。
定义接口的实现类
修饰符 class 类名 implements 接口1,接口2,...{
...
}
例如:
//定义接口
interface Student{
//常量
String NAME="张三";
int AGE=21;
//抽象方法
void say();
static int getAge(){
return Student.AGE;
}
//抽象方法
public void info();
}
//定义接口
interface Hobby{
public void running();
}
class Demo implements Student,Hobby{
@Override
public void say() {
System.out.println("好好学习,天天向上");
}
@Override
public void info() {
System.out.println("姓名:"+NAME);
}
@Override
public void running() {
System.out.println("喜欢跑步");
}
}
class TestDemo{
public static void main(String[] args) {
Demo demo = new Demo();
System.out.println("年龄:"+Student.getAge());
demo.info();
demo.say();
demo.running();
}
}
执行结果:
年龄:21
姓名:张三
好好学习,天天向上
喜欢跑步
注意事项:
1、接口除了两种方法,一种是static修饰的方法,另一种是被default修饰的方法外,只能包含抽象方法。
2、接口中的抽象方法,默认都是public abstract修饰的,成员变量都是public static final 修饰的。
如果一个类既要实现接口,又要继承抽象类,可以使用以下格式定义。
修饰符 class 类名 extends 父类名 implements 接口1,接口2...{
...
}