封装
面向对象的三大核心思想: 封装、继承、多态
1:概念
使一种屏障, 防止对象属性被外界任意访问,提高对象属性的安全性
步骤
-
属性私有化
private 数据类型 属性名;
访问修饰符 含义 作用范围 public 公共的,公开的 任意位置都可访问 private 私有的 只有本类内部可以访问 -
可以根据需求选择性的对属性进行私有化,但是通常情况下所有属性都应该私有化
-
-
提供取值赋值所需的getter\setter方法
-
getter: 取值. 有返回值,无参数
public 返回值类型 getXxx(){return 属性名; } Xxx:对应属性名,首字母大写如果属性是布尔类型,则该方法名为`isXxx`
-
返回值类型与对应属性保持一致
-
-
setter: 赋值. 没有返回值,有参数
public void setXxx(数据类型 属性名){this.属性名=属性名; } Xxx:对应属性名,首字母大写
-
可以根据需求为私有属性添加getter或setter方法,但是通常情况下所有私有属性都应该有配套的getter和setter方法
-
一个getter或setter方法只能操作一个属性
-
使用
给属性加上封装之后,必须通过调用getter和setter方法才能访问属性
取值: 对象名.getXxx()|对象名.isXxx() 赋值: 对象名.setXxx(实参)
package com.by.entity;
/*** 银行卡: 卡号、密码、余额*/
public class BankCard {private String cardID;private String password;private double balance;
//取值public String getCardID(){return cardID;}//赋值public void setCardID(String cardID){// this.cardID = cardID;System.out.println("卡号不可更改");}public String getPassword(){return password;}
public void setPassword(String password) {this.password = password;}
public double getBalance() {return balance;}
public void setBalance(double balance) {this.balance = balance;}public BankCard(){}
public BankCard(String cardID, String password, double balance) {this.cardID = cardID;this.password = password;this.balance = balance;}
}
package com.by.test;
import com.by.entity.BankCard;
public class TestBankCard {public static void main(String[] args) {BankCard bc = new BankCard("628888888888888","411381",1000.0);/* bc.balance = 1000000000.0;
System.out.println(bc.balance);System.out.println(bc.cardID);System.out.println(bc.password);*/
//赋值bc.setCardID("627777777777777");//取值System.out.println(bc.getCardID());
bc.setPassword("123456");System.out.println(bc.getPassword());
bc.setBalance(100000.0);System.out.println(bc.getBalance());
}
}
掌握
-
封装的步骤
-
getter、setter的区别
-
封装后的使用
2:继承
概念
将子类之间的共性进行抽取,生成父类.
在继承关系下,子类就可以默认拥有父类可别继承的内容
语法
class 子类类名 extends 父类类名{}
public class Animal {public String name;public int age;public String color;
public void eat(){System.out.println("吃饭");}public void sleep(){System.out.println("睡觉");}
}
public class Dog extends Animal{
}
public class Cat extends Animal{
}
规则
-
必须建立在is a关系之上
-
一个子类只能有一个直接父类 (单继承)
-
一个父类可以有多个直接子类
-
一个子类同时也可以是其他类的父类
-
子类中可以定义独有内容
-
父类无法访问子类的独有内容
-
子类可以继承拥有直接父类与间接父类中所有可被继承的内容
-
父类的私有内容子类无法直接继承访问
-
父类构造子类无法继承
子类的内存结构
-
子类的对象空间由
父类内容+独有内容
构成
父类封装
父类也是类,也应该按照要求进行属性的封装操作
package com.by.entity;
public class Animal {private String name;private int age;private String color;
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 getColor() {return color;}
public void setColor(String color) {this.color = color;}
public void eat(){System.out.println("吃饭");}private void sleep(){System.out.println("睡觉");}
}
使用
父类封装之后,子类将无法直接访问父类属性,必须通过调用getter()|setter()
的方式堆父类属性进行访问
public class Test2 {public static void main(String[] args) {Dog dog = new Dog();// dog.sleep();/*dog.name = "小黑";dog.age = 2;dog.color = "白色";*/dog.setName("小黑");dog.setAge(2);dog.setColor("白色");}
}
方法重写
-
又名方法覆盖
-
对从父类继承过来的方法进行方法体的重新书写,简称方法重写
规则
-
返回值类型、方法名、参数列表必须与父类保持一致
-
访问修饰符必须与父类相同或者更宽
-
不能抛出比父类更大或更多的异常
使用
子类进行方法重写之后,优先使用自身重写内容
父类的作用:
作为子类的共性抽取,解决子类之间的冗余问题
强制约束子类必须拥有某些特征和行为
有继承关系的对象创建过程
-
子类对象的构建
-
给父子类属性分配空间,赋默认值
-
给父类属性赋初始值
-
执行父类构造
-
给子类属性赋初始值
-
执行子类构造
super关键字
-
代表父类对象
super.
-
指明调用父类对象的属性或方法
super.属性名 super.方法名(实参)
-
无法调用父类的私有属性
super()
-
调用父类构造内容
使用
-
必须写在子类构造有效代码第一行
-
根据参数列表决定执行的是哪个父类构造
-
this()和super()不可同时显式存在
-
执行子类构造内容之前必定先执行父类构造内容
-
当子类构造中未显式调用父类构造时,默认存在无参的
super()
-
可以利用有参的super()直接在子类有参构造中给父类属性赋值
package com.by.entity; public class Animal {private String name;private int age;private String color; public Animal() {} public Animal(String name, int age, String color) {this.name = name;this.age = age;this.color = color;}//省略getter\setter } public class Dog extends Animal{public Dog(){} public Dog(String name, int age, String color) {super(name, age, color);} } public class Test4 {public static void main(String[] args) {Dog dog = new Dog("小黑", 2, "白色");System.out.println(dog.getName());System.out.println(dog.getAge());System.out.println(dog.getColor());} }
-
优化后的子类的有参构造:
访问修饰符 子类类名(父类的属性,独有的属性){super(父类属性);this.独有属性名=独有属性名; }
访问修饰符
-
控制内容可被访问的范围
本类 | 同包 | 非同包子类 | 非同包非子类 | |
---|---|---|---|---|
private(私有的) | √ | |||
default(默认的) | √ | √ | ||
protected(受保护的) | √ | √ | √ | |
public(公开的) | √ | √ | √ | √ |
-
都可以修饰属性、方法(普通方法、函数、构造)
-
都不可以修饰局部变量
-
只有public和default可以修饰掌握
-
继承的语法
-
继承的规则
-
方法重写的规则
-
有继承关系的对象创建过程
-
super关键字和this关键字的区别
-
四个访问修饰符及其作用范围
3:多态
概念
父类类型引用可以指向不同的子类对象
语法
父类类名 引用名=new 子类类名(); 父类引用=子类对象;
使用
-
建立在继承关系之上
-
实际创建的是子类对象
-
优先执行子类内容
-
父类引用无法访问子类的独有内容
-
编译失败
-
编译器关注的是引用类型,解释器关注的是实际对象类型
-
左边决定都能做什么,右边决定谁来做
-
-
引用类型间类型转换
自动类型转换
大类型 引用名=小类型引用名|小类型对象;
-
父类是大类型,子类是小类型
强转类型转换
小类型 引用名=(小类型)大类型引用名;
//利用多态创建Dog对象Animal a = new Dog();//将父类引用a强转为Dog引用Dog dog = (Dog) a;// Dog的引用.lookDoor();dog.lookDoor();
-
只能转向原本指向的子类类型
Animal a = new Dog(); Cat cat = (Cat) a; 错误!!
-
编译不报错,运行报错
-
java.lang.ClassCastException:类型转换异常
-
-
无父子类关系的子类之间不可进行强转
Dog d = new Dog(); Cat cat = (Cat) d; 错误!!
-
编译报错
-
多态的使用场景
-
用于容器: 将容器类型声明为大类型,则容器内部可以存放不同的小类型对象
Animal[] as = {new Dog(), new Dog(), new Cat(), new Cat()};//Animal as[0]=new Dog();//遍历数组,调用吃饭方法for (int i = 0; i < as.length; i++) {as[i].eat();}
-
用于参数: 将方法形参声明为大类型,则实参可以传入不同的小类型对象
public static void main(String[] args) {method1(new Dog());//狗吃大骨头method1(new Cat());//猫吃小鱼干} //定义一个函数,传入参数,可以执行出"狗吃大骨头"或"猫吃小鱼干"public static void method1(Animal a) {//Animal a=new Dog()//Animal a=new Cat()a.eat();}
-
用于返回值:将方法的返回值声明为大类型,则可以实际return不同的小类型对象
public static void main(String[] args) {//调用函数并接收返回值Animal a= method2(10);//Animal a=new Dog()a.eat();//狗吃大骨头// Dog d=(Dog)method2(10); }//定义一个函数,传入整型参数n,判断n的奇偶性,n为偶数返回Dog对象,n为奇数返回Cat对象public static Animal method2(int n){//Animal=new Dog()if (n % 2 == 0) {return new Dog();}return new Cat();}
instanceof关键字
-
判断当前对象是否与指定类型兼容
-
结果为布尔类型
引用名 instanceof 类名
public static void main(String[] args) {Animal[] as = {new Dog(), new Dog(), new Cat(), new Cat()};method(as);}//定义一个函数,传入一个Animal类型的数组,要求如果是Dog对象,执行"看门",如果是Cat对象,执行"猫吃小鱼干"public static void method(Animal[] as){for (int i = 0; i < as.length; i++) {if (as[i] instanceof Dog) {//将当前元素的类型强转为Dog类型Dog dog = (Dog) as[i];dog.lookDoor();} else {as[i].eat();}}}
使用
-
子类对象可以被父类类型兼容
-
父类引用只能被所指向的子类类型兼容
-
子类类型无法兼容父类对象
public static void main(String[] args) {Dog d = new Dog();System.out.println(d instanceof Dog);//tSystem.out.println(d instanceof Animal);//t
Dog jm = new JinMao();System.out.println(jm instanceof Dog);//tSystem.out.println(jm instanceof Animal);//t
Animal a = new Dog();System.out.println(a instanceof Animal);//tSystem.out.println(a instanceof Dog);//tSystem.out.println(a instanceof Cat);//fSystem.out.println(a instanceof JinMao);//f}
多态的好处
-
减少代码冗余
-
将代码解耦合,提高代码扩展性
掌握
-
多态的概念
-
多态的使用
-
引用类型间的强转
-
多态的三个使用场景(用法)
-
instanceof关键字的作用和语法