java大三特征

三大特征

一、概念

面向对象的语言一般应该具备三大特征:封装、继承和多态。

二、封装

下面的代码,年龄设置明显不符合实际,但是由于没有超出int的范围,所以不会报错。

public class Student {
    String name;
    int age;
    String sex;
}
​
public class Demo01 {
    public static void main(String[] args) {
        Student student = new Student();
        student.name = "张三";
        student.age = 20000;
        student.sex = "男";
    }
}

为了解决上面的问题,可以使用属性的封装。

2.1 属性封装

使用private关键字,将属性隐藏在类的内部,让外部不可访问,并添加一些外部可以访问属性的方法,来控制属性的修改和读取。

public class Student {
    private String name;
    private int age;
    private String sex;
    
    // 提供取值的方法
    public int getAge() {
        return this.age;
    }
    
    // 提供赋值的方法
    public void setAge(int age) {
        if(age <= 0 || age > 120) {
            System.out.println("不合法的年龄");
            this.age = 18;
        }else {
            this.age = age;
        }
    }
​
    public String getName() {
        if(this.name == null) {
            return "暂无";
        }else {
            return name;
        }
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public String getSex() {
        return sex;
    }
​
    public void setSex(String sex) {
        this.sex = sex;
    }
}

2.2 方法封装

将不需要暴露的方法隐藏(private),将需要外部使用的方法公开。

public class Kongtiao {
    // 需要外部调用的方法公开
    public void 制冷() {
        通电();
        压缩();
        送风();
    }
    
    // 不需要外部调用的方法,进行隐藏
    private void 通电() {
        System.out.println("通电");
    }
    
    private void 压缩() {
        System.out.println("压缩机启动");
    }
    
    private void 送风() {
        System.out.println("送风");
    }
}

三、继承

3.1 概念

子类通过继承的方式来继承父类的所有属性和方法。

语法:

class 子类 extends 父类{

}

优点:可以提高代码的重用性,减少代码的冗余。提供可扩展性和可维护性。

/**
 * 动物
 */
public class Animal {
    public String brand; // 种类
    public String sex; // 性别
    public int age; // 年龄
    
    public void eat() {
        System.out.println("动物在吃...");
    }
    
    public void sleep() {
        System.out.println("动物在睡...");
    }
}
​
public class Dog extends Animal{
}
​
public class Cat extends Animal{
}

Java中继承的特点:

单继承(一个类只能继承一个父类),但是可以多级继承,属性和方法逐级叠加。

注意:所有的类自动继承Object类。Object作为所有类的顶层父类。

class A{}

class A extends Object{}

上面两种写法使用上基本没有区别,但是直接继承Object会让该类不能再继承其他类,而间接继承Object还可以继承其他类。

3.2 不可继承

  • 构造方法只能创建本类的对象,视作不可继承。

  • 使用private修饰的属性和方法,只能本类可见,在子类中无法直接访问,视作不可继承。

  • 当没有访问修饰符修饰的属性和方法时,该访问修饰符为默认,只能在同一个包中访问,如果子类不在同一个包中,无法直接访问,视作不可继承。

3.3 访问修饰符

范围由小到大:private、默认(default)、protected、public

本类同包非同包子类其他
private×××
默认的××
protected×
public

3.4 方法重写

方法重写是指在子类定义一个与父类中完全相同的方法。会覆盖父类的方法。称为方法重写(override)

当父类的方法无法满足子类需求时,可以在子类中重写该方法。

语法要求:

  • 方法名称、参数列表、返回值类型、异常的声明必须与父类相同。

  • 访问修饰可以比父类更广。

public class A {
    public void m1() {
        System.out.println("A===m1");
    }
}
​
public class B extends A{
    @Override // 编译检查是否方法重写
    public void m1() {
        System.out.println("B===m1");
    }
}

可以使用@Override注解来编译检查方法是否构成重写,避免单词写错等误操作。

3.5 super关键字

  • 表示父类对象,调用父类的属性和方法

public class Animal {
    public String name = "Animal===name";
    
    public void eat() {
        System.out.println("动物在吃...");
    }
}
​
public class Dog extends Animal{
    public String name = "Dog====name";
    
    @Override
    public void eat() {
        // 当父类的方法不满足子类的需求,子类需要增强父类的方法中的内容
        // 为了避免代码的冗余,可以直接调用父类的方法
        super.eat();
        System.out.println("狗在吃...");
    }
    
    public void desc() {
        // 调用父类属性
        System.out.println(super.name);
        // 调用父类方法
        super.eat();
        System.out.println(name);
        eat();
    }
}
  • 调用父类的构造方法

public class Animal {
    private String name;
    private String sex;
    private int age;
    
    public Animal(String name, String sex, int age) {
        super();//调用Object类的无参构造方法
        this.name = name;
        this.sex = sex;
        this.age = age;
    }
}
​
public class Dog extends Animal{
    private String furColor;
    
    public Dog(String name, String sex, int age, String furColor) {
        // 调用父类的构造方法
        super(name, sex, age);
        this.furColor = furColor;
    }
}

注意:

  • 子类在继承父类后,子类的构造方法中会自动调用父类的无参构造方法。

  • 如果父类没有无参构造方法,那么子类会报错。解决方法:1、在父类中声明无参构造方法。2、在子类的构造方法中手动调用父类的有参构造方法。

  • 在构造方法中,如果调用父类的构造方法,必须放到第一行。

经典面试题:

this和super的异同:

  • 相同点:

    • 都可以调用属性和方法

    • 都可以调用构造方法

    • 调用构造方法时需要放在第一行

  • 区别:

    • this是调用当前类的属性和方法,以及构造方法。

    • super是调用父类的属性和方法,以及构造方法。

  • 注意:this和super在调用构造方法时,不能同时出现,一般出现了this,就不用super,然后在this调用的构造方法中去写super。

3.6 在继承时对象创建过程

在创建子类对象时会先创建父类对象。

流程:分配父类+子类的空间,先创建父类的对象,并且初始化父类的属性,调用父类的构造方法,再创建子类的对象,初始化子类的属性,调用子类的构造方法。

四、多态

4.1 基本使用

当使用父类的引用去引用子类的对象时,会呈现多种状态,称为多态。

注意:当使用父类的引用去引用子类对象时,只能使用父类的属性和方法。子类独有的属性和方法不能直接调用。

public class Demo1 {
    public static void main(String[] args) {
        // 可以使用父类的引用指向子类的对象
        Animal animal = new Dog();
        Animal animal1 = new Cat();
        // 不能使用子类的引用去引用父类的对象
//      Cat cat = new Animal();
    }
}

当在子类中重写了父类的方法,即使是通过父类的引用来调用该方法,也会执行子类重写之后的方法,因为毕竟是子类对象,而该对象中已经覆盖了父类的方法。

使用方法重载来描述主人喂养动物的案例:

public class Bird extends Animal{
	@Override
	public void eat() {
		System.out.println("鸟在吃...");
	}
}

public class Fish extends Animal{
	@Override
	public void eat() {
		System.out.println("鱼在吃...");
	}
}

// 主人
public class Master {
	// 喂养
	public void feed(Dog dog) {
		dog.eat();
	}
	
	public void feed(Cat cat) {
		cat.eat();
	}
	
	public void feed(Fish fish) {
		fish.eat();
	}
}

上面的代码每增加一种动物,都需要在主人类中添加一个喂养的方法,比较冗余,可以使用多态的方式。

public class Master {
	// 喂养
	public void feed(Animal animal) {
		animal.eat();
	}
    
    // 使用父类的引用,返回子类的对象
	public Animal playGame() {
		return new Dog();
	}
}

此时,无论传入的是何种动物,都可以适用,而且由于子类重写了eat方法,都会去调用子类重写之后的方法。

public class Demo1 {
	public static void main(String[] args) {
		Master master = new Master();
		Dog dog = new Dog();
		master.feed(dog);
		Cat cat = new Cat();
		master.feed(cat);
		Fish fish = new Fish();
		master.feed(fish);
		Animal animal = new Bird();
		master.feed(animal);
		master.feed(new Dog());
	}
}

4.2 装箱和拆箱

装箱:将子类对象使用父类的引用去指向。会自动完成装箱。

Animal a = new Cat();

拆箱:使用父类引用的子类对象,使用子类的引用去指向,称为拆箱,需要强制转换。

Animal a = new Dog();
Dog d = (Dog)a;

4.3 类型转换异常

当拆箱使用类型不当时,会出现类型转换异常。ClassCastException

Animal a = new Cat();
Dog d = (Dog)a; // 会出现ClassCastException

4.4 instanceof关键字

要避免类型转换异常,可以使用instanceof关键字来判断对象的类型。返回boolean值。

// 主人
public class Master {
	// 喂养
	public void feed(Animal animal) {
		animal.eat();
		
		// 如果是狗类对象
		if(animal instanceof Dog) {
			Dog dog = (Dog)animal;
			dog.watch();
		}else if(animal instanceof Cat) {
			Cat cat = (Cat)animal;
			cat.pa();
		}else if(animal instanceof Bird) {
			Bird bird = (Bird)animal;
			bird.fly();
		}else if(animal instanceof Fish) {
			Fish fish = (Fish)animal;
			fish.swim();
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值