目录
2、用final修饰的方法不能被Override:用final修饰的类不能被继承。如果一个类不希望任何其他类继承自它,那么可以把这个类本身标记为final。
3、对于一个类的实例字段,同样可以用final修饰。用final修饰的字段在初始化后不能被修改。
5、可以在构造方法中初始化final字段:这种方法更为常用,因为可以保证实例一旦创建,其final字段就不可修改。
面向对象的三大特征:
一、继承:
1、定义:
继承是面向对象编程中非常强大的一种机制,它首先可以复用代码。当我们让子类
从父类继承时,子类
就获得了父类
的所有功能,我们只需要为子类
编写新增的功能。Java
中使用extends
关键字来实现继承:
修饰符 class 子类名 extends 父类{
// 非私有的成员变量
// 非私有的成员方法
// 自定义成员变量和成员方法
}
2、特点:
(1)java允许单继承,不允许多继承
(2)允许多级继承
(3)允许一个父类拥有多个子类
package com.yuan;
public class Demo01 {
public static void main(String[] args) {
C c = new C();
c.hello();
}
}
class A{
public void hello(){
System.out.println("hello");
}
}
class B extends A{
}
class C extends B{
}
3、 继承树:
我们在定义父类
的时候,没有写extends
。在Java
中,没有明确写extends
的类,编译器会自动加上extends Object
。所以,任何类,除了Object
,都会继承自某个类。下图是Person
、Student
的继承树:
4、protected 关键字:
使用范围: 可以让子类和同包下的类访问。
继承有个特点,就是子类无法访问父类的private
字段或者private
方法。例如,Student
类就无法访问Person
类的name
和age
字段:
class Person {
private String name;
private int age;
}class Student extends Person {
public String hello() {
return "Hello, " + name; // 编译错误:无法访问name字段
}
}
使用protected继承的作用就会被削弱了。为了让子类可以访问父类的字段,我们需要把private
改为protected
。用protected
修饰的字段可以被子类访问:
class Person {
protected String name;
protected int age;
}class Student extends Person {
public String hello() {
return "Hello, " + name; // OK!
}
}
5、super 关键字:
(1)super
关键字:
表示父类(超类)。子类引用父类的字段时,可以用super.fieldName
。例如:
class Student extends Person {
public String hello() {
return "Hello, " + super.name;
}
}
2、super():
子类在继承父类的时候,子类的构造方法会默认调用父类的无参构造方法,如果父类没有无参构造,需要手动调用父类的有参构造:
//定义父类 public class Person { public String cardId; protected String name; protected int age; //定义有参构造默认无参构造没有 public Person(String name, int age) { this.name = name; this.age = age; } } //定义子类 class Student extends Person{ public int score; public String name; //子类的构造方法会默认调用父类的无参构造方法 // 如果父类没有无参构造,需要手动调用父类的有参构造 public Student(){ //手动调用 super("张三",8); } public Student(String name, int age,int score) { super(name, age); this.score=score; } //就近原则 //如果此方法有变量,则优先用此方法的局部变量 //如果此方法没有这个局部变量,则找本类的成员变量 //如果本类的成员变量没有,则找父类 //如果强制指代此变量为本类,可以用this,如果声明此变量为父类的用super //Object 中的equals方法比较地址 public void showMessage(String name) { System.out.println( "使用super调用:{" + "name='" + super.name + ", age=" + super.age + ", score=" + this.score + '}'); System.out.println( "使用this调用:{" + "name='" + this.name + ", age=" + this.age + ", score=" + this.score + '}'); System.out.println( "不使用关键字调用:{" + "name='" + name + ", age=" + age + ", score=" + score + '}'); //就近原则 } } class Test{ public static void main(String[] args) { Student student = new Student(); // System.out.println(student.name); // System.out.println(student.age); //有参构造 Student student1 = new Student("王麻子",18,100); // System.out.println(student1.name); // System.out.println(student1.age); student1.showMessage("李四"); } }
6、向上转型:
父类的引用执行具体的子类 只能使用父类拥有的
三种方式:
1、直接转:
直接向上转型:父类的引用执行具体的子类 只能使用父类拥有的
Animal2 a1=new Cat2("花花",3,'黑'); //第一种
Brid b3=new Brid("点点",2,'白'); //第二种
Animal2 a3=b3; //向上转型
2、参数转:
Brid b1 = new Brid("扁扁", 2, '彩');
keepPet(b1, "谷子");//2、参数的向上 keepPet(Animal a,int age ,char ch){}
3、返回值做到了上转型
public static Animal getAnimal(){
return new Brid("扁扁", 2, '彩');
}
7、向下转型:
将对外声明的父类对象转回为具体的子类,向下转型,具有不安全的。可能会出现类型转换异常ClassCastException ,所有的向下转型在进行转换前,需要进行判断,判断当前对象是否属于要转的这种类型
Animal2 a4=new Cat2("花花",3,'黑');
System.out.println(a4.weight);
a4.catchMouse(); //报红 是Cat独有的方法 需要向下转型为Cat类型
Cat2 c4=(Cat2)a4;
System.out.println(c4.weight);
c4.catchMouse();
2、
Animal2 a5=new Brid("点点",2,'白');
Brid b4=(Brid) a5; //向下转型
b4.fly();/// 使用自己独有的方法
b4.eat("虫子"); //自己为定义eat 此时使用父类eat
3、子类之间不可以相互转型:会出现类型转换异常 使用instanceof 判断是不是同一个类型
Animal2 a6=new Cat2("远远",3,'黑');
if(a6 instanceof Brid) { //结果为布尔类型
Brid c1 = (Brid) a6; //子类之间不可相互转型 类型转换异常
}else {
System.out.println("不是鸟的类型");
}
二、方法重写:
1、定义:
在继承关系中,子类如果定义了一个与父类方法签名完全相同的方法,被称为重写(Override
)。Override
重写和Overload
重载不同的是:如果方法签名不同,就是Overload
重载,Overload
重载方法是一个新方法;如果方法签名相同,并且返回值也相同,就是Override
重写。加上@Override
注解可以让编译器帮助检查是否进行了正确的覆写。希望进行覆写,但是不小心写错了方法签名,编译器会报错。
class Person {
public void run() { … }
}class Student extends Person {
// 不是Override,因为参数不同:
public void run(String s) { … }
// 不是Override,因为返回值不同:
public int run() { … }
}
2、调用super:
在子类的重写方法中,如果要调用父类的被覆写的方法,可以通过super
来调用。
class Person {
protected String name;
public String hello() {
return "Hello, " + name;
}
}Student extends Person {
@Override
public String hello() {
// 调用父类的hello()方法:
return super.hello() + "!";
}
}
3、 final关键字
1、 继承可以允许子类覆写父类的方法。如果一个父类不允许子类对它的某个方法进行覆写,可以把该方法标记为final
。
class Person {
protected String name;
public final String hello() {
return "Hello, " + name;
}
}Student extends Person {
// compile error: 不允许覆写
@Override
public String hello() {
}
}
2、用final
修饰的方法不能被Override
:用final
修饰的类不能被继承。如果一个类不希望任何其他类继承自它,那么可以把这个类本身标记为final
。
final class Person {
protected String name;
}// compile error: 不允许继承自Person
Student extends Person {
}
3、对于一个类的实例字段,同样可以用final
修饰。用final
修饰的字段在初始化后不能被修改。
class Person {
public final String name = "Unamed";
}
4、对final
字段重新赋值会报错
Person p = new Person();
p.name = "New Name"; // compile error!
5、可以在构造方法中初始化final
字段:这种方法更为常用,因为可以保证实例一旦创建,其final
字段就不可修改。
class Person {
public final String name;
public Person(String name) {
this.name = name;
}
}