目录
1.继承
1.1 继承的语法
类与类之间的继承用extends关键字
class Animal {
public String name;
public int age;
public void eat() {
System.out.println(name + "正在吃饭");
}
private int hehe;
}
// 子类 继承 父类
class Dog extends Animal {
public void dack() {
System.out.println(name + " 在汪汪叫 " + "年龄:" + age);
}
}
上面的代码是Dog类继承了Animal类
子类继承父类之后,会将父类的所有属性和方法都继承过来,但是父类中被private修饰的成员不可以直接访问
class Animal {
public String name;
public int age;
public void eat() {
System.out.println(name + "正在吃饭");
}
private int hehe;
}
// 子类 继承 父类
class Dog extends Animal {
public void dack() {
System.out.println(name + " 在汪汪叫 " + "年龄:" + age);
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "旺财";
dog.age = 10;
//dog.hehe = 100; //父类中的私有权限不可以直接访问 可以通过对外接口的方式
dog.eat();
dog.dack();
}
}
1.2 子类中与父类重名成员的访问
子类中如果有成员和父类的成员重名,那么在调用时不会调用父类的成员,会优先调用子类的成员
class Animal {
public String name = "haha";
public int age;
public void eat() {
System.out.println(name + "正在吃饭");
}
private int hehe;
}
class Dog extends Animal {
public String name = "hehe";
public void dack() {
System.out.println(name + " 在汪汪叫 " + "年龄:" + age);
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println(dog.name);
}
}
这时的打印是hehe
1.3 super关键字
如果我们想在子类方法中调用父类的重名成员就要用super关键字。
调用父类的普通成员变量和方法直接用 super. 即可
当调用父类的构造方法是则要用到super(...)
在调用子类的构造方法时,需要先调用父类的构造方法
调用方法就是super() 括号里面进行传参,并且super()必须在子类构造方法的第一条语句,如果子类的构造方法里没有写super(),那么编译器会默认生成一个空的super()。
class Animal1 {
public String name;
public int age;
public Animal1() {
}
public Animal1(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Animal1(String ,int )");
}
public void eat() {
System.out.println(name + " 吃饭 ");
}
public static void staticEat() {
System.out.println("父类静态方法");
}
}
/**
* super
* super. 在子类中可以调用 父类普通成员 变量
* super. 在子类方法中可以调用 父类普通成员 方法
* super() 调用父类构造方法
*/
class Dog1 extends Animal1 {
public boolean still;
public String name = "hello";
//调用子类的构造方法要先调用父类的构造方法
//不构造会默认给一个super()
public Dog1(String name, int age, String name1, boolean still) {
super(name, age);
this.name = name1;
this.still = still;
}
public void func() {
super.staticEat();//不建议用super调用父类的静态方法
System.out.println(super.name + " " + age + " " + name + " " + still);
}
}
1.4 子类与父类中代码块和构造方法的执行顺序
调用顺序为 先静态,后实例,再构造 在继承中会先将父类的实例和构造调用完,再调用子类的实例和构造 1.父类的静态 2.子类的静态 3.父类的实例 4.父类的构造 5.子类的实例 6.子类的构造
package inherit;
/**
* 调用顺序为
* 1.父类的静态 2.子类的静态
* 3.父类的实例 4.父类的构造
* 5.子类的实例 6.子类的构造
*/
class Animal1 {
public String name;
public int age;
public Animal1() {
}
static {
System.out.println("Animal1::static{}");
}
{
System.out.println("Animal1::{}");
}
public static void staticEat() {
System.out.println("父类静态方法");
}
}
class Dog1 extends Animal1 {
public boolean still;
public String name = "hello";
static {
System.out.println("Dog1::static{}");
}
{
System.out.println("Dog1::{}");
}
}
public class Test2 {
public static void main(String[] args) {
Dog1 dog1 = new Dog1("hello", 10, "heihei", false);
}
}
输出的顺序则是:
Animal1::static{}
Dog1::static{}
Animal1::{}
Animal1(String ,int )
Dog1::{}
Dog1(String ,int ,String ,boolean )
1.5 继承方式
Java中的继承,可以将父类继承给多个子类,但是一个子类只能继承一个父类,不可以进行多继承,如果想继承多个类,可以让继承的父类去继承其他类。
1.6 final关键字
final可以修饰变量,方法,类
被final修饰的变量,表示为常量,不可以再被修改
被final修饰的方法不可以被重写(多态会说明重写)
被final修饰的类不可以被继承
//此时Animal类将不能被继承
public final class Animal {
...
}
2.多态
2.1 重写
父类中的方法在子类中被重新实现,称为重写
所谓重写,是将父类方法的外壳保存,只将里面的内容进行修改
被重写的方法不可以是构造方法 也不可以是被static、final、private修饰的方法,且重写后的方法,其使用权限一定是 大于等于 重写前的方法的。
class Animal00 {
public String name;
public int age;
public void eat() {
System.out.println(name + " 吃饭 ");
}
}
/**
* 子类Dog00中的eat()方法是 父类Animal00类中eat()方法的重写
* 父类中被private限定符修饰的不可以被重写
* 重写的方法的范围一定要大于等于重写前方法的范围
* 但是不能对呗 final 或者 static 修饰的方法以及 构造方法 进行重写
*/
class Dog00 extends Animal00 {
public boolean still;
public String name;
public void eat() {
System.out.println(name + "正在吃狗粮");
}
}
2.2 向上转型和向下转型
2.2.1 向上转型
向上转型是小范围向大范围的转型,也就是子类对象转型成父类对象
Animal00 animal = new Dog00();
父类对象向上转型之后只可以访问父类自己特有的属性和方法,不可以访问子类特有的属性和方法
在被调用子类重写后的方法时,不会调用父类的方法,而是调用子类重写后的方法,这个时候,多态就被体现出来了
public static void function(Animal00 animal) {
animal.eat();
}
public static void main(String[] args) {
//向上转型 小范围向大范围转换
Animal00 animal = new Dog00("哈士奇", 10, "德牧", false);
function(animal);
Cat00 cat = new Cat00("咪咪", 20);
Animal00 animal1 = cat;
function(animal1);
}
2.2.2 向下转型
当子类对象转型成父类对象后,还想调用子类特有的属性,这是要用到向下转型。
public static void main4(String[] args) {
Animal00 animal = new Cat00("咪咪", 10);
Cat00 cat = (Cat00) animal;//向下转型
cat.funcm();//Cat00类特有方法
cat.eat();//Animal00类的特有方法
}
但是向下转型是很不安全的,因为如果有多个类继承了同一个父类,那么在转型时可能出现在同属与Animal类的Dog类对象去调用Cat类对象的情况,这是不允许的,所以Java中引入了instanceof
左侧放父类,右边放子类则返回true
右边不是子类则返回false
public static void main5(String[] args) {
Animal00 animal00 = new Dog00("二哈", 18, "二哈000", true);
//如果是返回true 不是返回false
if (animal00 instanceof Cat00) {
Cat00 cat = (Cat00) animal00;
cat.funcm();
}
}
这样提高了代码的安全性
2.3 避免在构造方法中调用重写方法
因为在调用子类的构造方法时,会先调用父类的构造方法,如果这时在父类的构造方法中调用重写的方法,由于子类对象还没有构造,可能会出现属性未初始化的现象。