面向对象三大特征
封装
继承
多态
封装
概述
是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。核心是归纳总结
好处
提高代码的复用度、安全性,不必关心具体细节,便于开发
JavaBean 规范化封装
1. 要求Java中的所有实体类成员变量全部私有化,最少提供一个无参数构造方法,对应成员变量实现setter和getter方法
2. JavaBean规范,是为了后期开发汇总更好的代码适配度,提高代码运行的统一性,能够满足框架的使用
3. JavaBean规范只是一个规范,而且是作为一个基础规范,操作都是可以使用快捷键来完成的!!!
class Person {
private String name;
private int age;
private char sex;
private boolean alive;
public Person() {}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public char getSex() {
return this.sex;
}
public boolean isAlive() {
return alive;
}
public void setAlive(boolean alive) {
this.alive = alive;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSex(char sex) {
this.sex = sex;
}
}
类与类之间的调用(多类合作)
汽车类
public class Car {
private String color;
private float speed;
private int tyreTotal;
// 将自定义的引擎类作为汽车类的成员变量
private Engine engine;
public Car() {
super();
}
public Car(String color, float speed, int tyreTotal, Engine engine) {
super();
this.color = color;
this.speed = speed;
this.tyreTotal = tyreTotal;
this.engine = engine;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public float getSpeed() {
return speed;
}
public void setSpeed(float speed) {
this.speed = speed;
}
public int getTyreTotal() {
return tyreTotal;
}
public void setTyreTotal(int tyreTotal) {
this.tyreTotal = tyreTotal;
}
public Engine getEngine() {
return engine;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
/**
* 飙车方法,如果轮胎个数不为4,需要找修理厂
*/
public void race() {
if (4 == tyreTotal) {
System.out.println("开着" + this.color + "颜色的保时捷以" + speed + "迈的速度飙车");
} else {
System.out.println("轮胎出问题了,要找修理厂");
}
}
}
修理厂类
public class Factory {
private String name;
private String tel;
private String address;
public Factory() {
super();
}
public Factory(String name, String tel, String address) {
super();
this.name = name;
this.tel = tel;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
/**
* 修车方法,需要传入一辆汽车
*
* @param car 传入需要修理的车对象
* @return 返回修好的车
*/
public Car fix(Car car) {
System.out.println("欢迎来到" + this.name + "修车厂,我们的电话是:" + this.getTel() + ",我们的地址是:" + this.address);
if (car.getTyreTotal() != 4) {
car.setTyreTotal(4); // 将轮胎改成4个
car.setSpeed(80.0F); // 速度降到80迈
System.out.println("修车ing~~~");
}
// 拿到汽车的引擎
Engine engine = car.getEngine();
// 拿到引擎的名字和排量
String engineName = engine.getName();
float engineDisplacement = engine.getDisplacement();
if (null != engineName) {
System.out.println("检查引擎没有问题,排量是:" + engineDisplacement + "T");
}
System.out.println("修理完毕");
return car;
}
}
引擎类
public class Engine {
// 型号
private String name;
// 排量
private float displacement;
public Engine() {
super();
}
public Engine(String name, float displacement) {
super();
this.name = name;
this.displacement = displacement;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getDisplacement() {
return displacement;
}
public void setDisplacement(float displacement) {
this.displacement = displacement;
}
}
测试类
public class TestCar {
public static void main(String[] args) {
// 这里有一个引擎
Engine engine = new Engine();
engine.setName("XX");
engine.setDisplacement(1.0F);
// 买了一辆保时捷
Car car = new Car("红色", 300.0F, 4, engine);
// 飙车
for (int i = 1; i <= 10; i++) {
car.setSpeed(car.getSpeed() + 2);
car.race();
}
// 如果车的速度太快,达到了320迈,就会爆胎
if (car.getSpeed() >= 320.0) {
// 有一个车轱辘爆胎了
car.setTyreTotal(3);
}
// 继续飙车
car.race();
// 找修理厂
Factory factory = new Factory("摇滚王子修车厂", "15844517927", "吉安");
// 修车,拿到修好的车
Car fixedCar = factory.fix(car);
// 飙车
for (int i = 1; i <= 10; i++) {
fixedCar.setSpeed(fixedCar.getSpeed() + 2);
fixedCar.race();
}
// 随便找个修车厂修车,此时我只关心修车,不在乎其他的内容
// new Factory().fix(car);
}
}
匿名对象
概述
没有名字的对象,是对象的一种简化表示形式
特性
一次性,每次使用都是一个新的对象
使用情景
1、对象调用方法仅使用一次,然后等待销毁
2、作为实际参数传递
public class TestDog{
public static void main(String[] args) {
// 对象调用方法仅使用一次
new Dog().sleep();
// 作为实际参数传递
useDog(new Dog());
}
public static void useDog(Dog dog) {
dog.sleep();
}
}
class Dog {
String name;
int age;
public void sleep() {
System.out.println("小狗睡觉.....");
}
}
优点
提高开发效率,简化代码结构
继承
概念
把多个类中相同的成员给提取出来定义到一个独立的类中。然后让这多个类和该独立的类产生一个关系,这多个类就具备了这些内容。这个关系叫继承。
关键字:extends
格式:
class Son extends Father {
}
一个孩子只能有一个父亲
一个父亲可以有多个孩子
特点
1、Java为单继承,一个类只能有一个直接父类,但可以多级继承,属性和方法逐级叠加
2、构造方法只可服务于本类,不可继承,子类执行构造方法前会默认调用父类的无参构造方法。可以通过super()去访问父类的构造方法
3、private 修饰的属性和方法不能被继承
extends
public class Demo {
public static void main(String[] args) {
// 创建一个父类对象
Father father = new Father();
// 父类调用父类的属性和方法
father.name = "父";
System.out.println(father.name);
father.game();
System.out.println("-------------");
// 创建一歌子类对象
Son son = new Son();
// 子类调用子类的属性和方法
son.age = 16;
System.out.println(son.age);
son.study();
// 子类调用父类的属性和方法(public修饰)
son.name = "子";
System.out.println(son.name);
son.game();
/*
* 子类调用父类private修饰的属性和方法
*
* 报错
* The field Father.suffer is not visible
* The method cook() from the type Father is not visible
*
* 由此可知子类不能调用父类私有化的属性和方法
*/
// son.suffer = 10;
// son.cook();
}
}
public class Father {
public String name;
private int suffer;
public void game() {
System.out.println("下棋");
}
private void cook() {
System.out.println("做饭");
}
}
public class Son extends Father{
public int age;
public void study() {
System.out.println("子类 -- 学习");
}
}
子类构造方法执行前默认先执行父类的无参构造方法
class Father {
String name;
public Father() {
System.out.println("Father's Constrator be performed");
}
}
class Son extends Father {
int age;
public Son() {
System.out.println("Son's Constrator be performed");
}
}
public class TestSon {
public static void main(String[] args) {
Son son = new Son();
}
}
结果
Father's Constrator be performed
Son's Constrator be performed
【注意】Son 的构造方法中编译器默认生成 super(); 用来调用父类的构造方法,目的是为了初始化父类字段,因为子类可能会用到
继承内存分析图 |
---|
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QCqczLWa-1659320475378)(Pictures\继承内存分析图.jpg)] |
优点
1、提高了代码的复用性
2、提高了代码的维护性
3、让类与类之间产生了一个关系,是多态的前提
缺点
1、让类的耦合性增强。这样某个类的改变,就会影响到其他和该类相关的类
2、打破了封装性
总结
Java中只有单继承
子类可以继承父类的非私有属性和方法(非private修饰的)
执行子类的构造方法前会默认执行父类的无参构造方法
方法重写【Override】
引言
开发中父类的方法不一定适用于子类,因为父类方法不能更改,在子类中新增方法会造成代码的冗余,而且不符合逻辑
要求
1、应用于继承和实现接口
2、返回值类型,方法名,形参列表与父类一致
3、使用@Override注解来标识
4、重写方法的访问修饰符权限不能低于父类
private < 默认(什么都不写) < protected < public
public class Son extends Father{
public int age;
@Override
public void game() {
System.out.println("玩红色警戒");
}
public void study() {
System.out.println("子类 -- 学习");
}
}
public class Father {
public String name;
private int suffer;
public void game() {
System.out.println("下棋");
}
private void cook() {
System.out.println("做饭");
}
}
public class Demo1 {
public static void main(String[] args) {
Son son = new Son();
son.game();
}
}
优点
既沿袭了父类的方法名,又实现了子类的扩展
总结
1、方法的重写能够在不新增方法的情况下实现子类的扩展
2、方法重写要求方法声明格式和父类完全一致(访问修饰符不能小于父类)
3、@Overrid关键字用来开启格式检测,如果不一致就会报错
多态
二者具有直接或间接的继承关系时,父类引用指向子类对象,从而产生多种形态;接口的引用指向实现接口的类对象也是多态
特点
多态场景下,父类引用调用方法,如果被子类重写过,优先执行子类重写过后的方法
public class TestCar {
public static void main(String[] args) {
// 父类引用指向子类对象
Vehicle vehicle = new Car();
// 优先执行子类重写过的方法
vehicle.run(); // Car run!!!
}
}
class Vehicle {
public void run() {
System.out.println("Vehicle run!!!");
}
}
class Car extends Vehicle {
@Override
public void run() {
System.out.println("Car run!!!");
}
}
应用场景一
使用父类作为方法形参实现多态,使方法参数的类型更为宽泛
public class TestCar {
public static void main(String[] args) {
Vehicle vehicle = new Car();
vehicle.type = "小汽车";
Bike bike = new Bike();
bike.type = "自行车";
Bus bus = new Bus();
bus.type = "公交车";
Employee employee = new Employee("你的迪丽热巴");
employee.goHome(vehicle);
employee.goHome(bus);
}
}
class Employee {
String name;
public Employee() {
}
public Employee(String name) {
this.name = name;
}
public void goHome(Vehicle vehicle) {
System.out.println(this.name + "乘坐" + vehicle.type + "交通工具回家");
}
}
class Vehicle {
String type;
public void run() {
System.out.println("Vehicle run!!!");
}
}
class Bus extends Vehicle {
@Override
public void run() {
System.out.println("Bus run!!!");
}
}
class Car extends Vehicle {
@Override
public void run() {
System.out.println("Car run!!!");
}
}
class Bike extends Vehicle {
@Override
public void run() {
System.out.println("Bike run!!!");
}
}
结果
你的迪丽热巴乘坐小汽车回家
Car run!!!
你的迪丽热巴乘坐公交车回家
Bus run!!!
应用场景二
使用父类作为方法返回值实现多态,使方法可以返回不同子类对象
public Vehicle buyVehicle(int money) {
Vehicle vehicle = null;
if (money >= 100) {
Bus bus = new Bus();
bus.speed = 60;
bus.price = 1230000.0;
bus.seatNum = 16;
bus.type = "公交车";
vehicle = bus;
} else if (money >= 30) {
Car car = new Car();
car.price = 310000.0;
car.speed = 90;
car.type = "小汽车";
car.brand = "BMW";
vehicle = car;
} else if (money >= 1) {
Bike bike = new Bike();
bike.type = "捷安特自行车";
bike.speed = 40;
bike.price = 2000.0;
bike.color = "红色";
vehicle = bike;
}
return vehicle;
}
向上装箱与向下拆箱
class Animal{}
class Cat extends Animal{}
class Dog extends Animal{}
class Fish extends Animal {}
public class Test {
public static void main(String[] args) {
showAnimal(new Animal()); // code.polymorphic.animal.Animal@7852e922
// 向上转型
showAnimal(new Cat()); // code.polymorphic.animal.Cat@4e25154f
// 向上转型
showAnimal(new Dog()); // code.polymorphic.animal.Dog@70dea4e
// 向上转型
showAnimal(new Fish()); // code.polymorphic.animal.Fish@5c647e05
System.out.println("----------------------");
Animal animal = getAnimal();
// 向下转型
Cat cat = (Cat) getCat();
// 向下转型
Dog dog = (Dog) getDog();
// 向下转型
Fish fish = (Fish) getFish();
System.out.println(animal); // code.polymorphic.animal.Animal@33909752
System.out.println(cat); // code.polymorphic.animal.Cat@55f96302
System.out.println(dog); // code.polymorphic.animal.Dog@3d4eac69
System.out.println(fish); // code.polymorphic.animal.Fish@42a57993
}
/**
* 展示动物
* @param animal
*/
public static void showAnimal(Animal animal) {
System.out.println(animal);
}
/**
* 得到动物
* @return 返回一个Animal对象
*/
public static Animal getAnimal() {
return new Animal();
}
/**
* 得到猫
* @return 返回一个Cat对象
*/
public static Animal getCat() {
return new Cat();
}
/**
* 得到狗
* @return 返回一个Dog对象
*/
public static Animal getDog() {
return new Dog();
}
/**
* 得到鱼
* @return 返回一个Fish对象
*/
public static Animal getFish() {
return new Fish();
}
}
instanceof 关键字
用于判断当前对象是否是某个类,或者其子类、实现类的实例。如果是返回true,否则返回false。
/**
* 动物类
*/
class Animal {
}
/**
* 老虎类
*/
class Tiger extends Animal {
}
/**
* 熊猫类
*/
class Panda extends Animal {
}
/**
* 猴子类
*/
class Monkey extends Animal {
}
public class AnimalDemo {
public static void main(String[] args) {
Animal ani = getAnimal();
if (ani instanceof Panda) {
// ani一定是panda对象或子类对象
Panda panda2 = (Panda) ani;
System.out.println("这是熊猫:" + panda2);
showPanda(panda2);
} else {
System.out.println("这是动物:" + ani);
}
}
// 获取动物,返回一个Panda对象
public static Animal getAnimal() {
return new Panda();
}
// 展示熊猫对象
public static void showPanda(Panda panda) {
System.out.println(panda);
}
}
【注意】使用 instanceof 关键字做判断时, instanceof 操作符的左操作数必须和右操作类或者接口存在继承或实现关系
总结
1、父类引用指向子类对象,接口引用指向实现类对象
2、instanceof用以比较对象是否是类或父类的实例,接口的实现类