封装
就是把抽象的数据【属性】和对数据的操作【方法】封装在一起,数据被保护在内部,程序的其他部分只有通过授权的操作【方法】才能对数据进行操作
封装的实现步骤
1、将属性私有化 private
2、提供一个公共的(public)set方法,用于对属性判断并赋值
public void setXxx(类型 参数名){
// Xxx表示某个属性
// 加入数据验证的业务逻辑
属性=参数名
}
3、提供一个公共的(public)get方法,用于获取属性的值
public 数据类型 getXxx(){
//增加权限判断
return Xxx
}
封装验证
1、普通验证
创建无参构造器,调用set方法验证
Person person = new Person();
person.setName("大");
person.setAge(18);
System.out.println(person.info());
public Person(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
if (name.length() >= 2 && name.length() <= 6) {
this.name = name;
} else {
System.out.println("你设置的名字长度不合理,默认名字天美");
this.name = "天美";
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 1 && age < 120) {
this.age = age;
} else {
System.out.println("你设置的年龄不合理,默认年龄8");
this.age= 8;
}
}
2、将构造器和set方法结合在初始化对象的时候进行验证
Person person = new Person("1", 118, 2326);
System.out.println(person.info());
public Person(String name, int age, double salary) {
// this.name = name;
// this.age = age;
// this.salary = salary;
setName(name);
setAge(age);
setSalary(salary);
}
public String getName() {
return name;
}
public void setName(String name) {
if (name.length() >= 2 && name.length() <= 6) {
this.name = name;
} else {
System.out.println("你设置的名字长度不合理,默认名字天美");
this.name = "天美";
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 1 && age < 120) {
this.age = age;
} else {
System.out.println("你设置的年龄不合理,默认年龄8");
this.age= 8;
}
}
继承
继承作用
当两个类的部分属性和方法相同时,使用继承,可以解决代码的复用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dFTXFtvb-1680138080440)(C:\Users\27310\AppData\Roaming\Typora\typora-user-images\image-20230130104824010.png)]
继承的基本语法
class 子类 extends 父类{
1、子类会自动拥有父类定义的属性和方法
2、父类又叫超类,基类
3、子类又叫派生类
}
继承的注意事项及使用细节
1、子类继承了所有的属性和方法,非私有的属性和方法可以直接访问,私有的属性和方法需要通过父类提共的公共方法进行访问
2、子类最多只能继承一个父类(直接继承),即java是单继承机制
构造器调用的具体细节
1、继承了之后,子类必须调用父类的构造器,完成父类的初始化
2、如果希望指定去调用父类的构造器,super(参数列表)
3、super 只能在构造器中使用
4、构造器的调用只能放在构造器里面的第一条语句上,
5、父类构造器的调用不限于直接父类,会一直追溯到Object类(顶级父类)
6、构造器在对象初始化的时候被调用,当初始化有参构造器时,无参构造器会被顶替掉,此时系统不会自动调用无参构造器
1、初始化的是无参构造器
public class TextExtends02 {
public static void main(String[] args) {
Sub sub = new Sub();
}
}
class TopBase {//父类的父类的Object
public TopBase() {
System.out.println("构造器TopBase被调用");
}
}
class Base extends TopBase {
public Base() {
System.out.println("父类中的Base()构造器被调用...");
}
public Base(String name, int age) {
System.out.println("父类的Base(String name, int age)被调用");
}
public Base(String name) {
System.out.println("父类的Base(String name)被调用");
}
class Sub extends Base {
public Sub(String name, int age) {
//希望调用父类中的无参构造器
super("大黄", 45);
System.out.println("子类中的(String name,int age)被调用");
}
public Sub() {
super();
System.out.println("子类中的Sub()构造器被调用");
}
public Sub(String name) {
super("大狗", 30);
System.out.println("子类中的Sub(String name)构造器被调用");
}
public void sayOk() {//子类中的方法
System.out.println(n1 + " " + n2 + " " + n3);
test100();
test200();
test300();
//提供的特有方法去访问
System.out.println("n4" + getN4());
callTest400();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nTpGHLTv-1680138080441)(C:\Users\27310\AppData\Roaming\Typora\typora-user-images\image-20230130113350616.png)]
2、初始化的是一个参数的构造器
此时,调用了Sub的一个参数的构造器,这个构造器中,利用 super(“大狗”, 30)调用到了父类的两个参数的构造器,有参构造器顶替掉了无参构造器,所以系统不会调用Base的无参构造器
public class TextExtends02 {
public static void main(String[] args) {
Sub sub1 = new Sub("jack");
}
}
class TopBase {//父类的父类的Object
public TopBase() {
System.out.println("构造器TopBase被调用");
}
}
class Base extends TopBase {
public Base() {
System.out.println("父类中的Base()构造器被调用...");
}
public Base(String name, int age) {
System.out.println("父类的Base(String name, int age)被调用");
}
public Base(String name) {
System.out.println("父类的Base(String name)被调用");
}
class Sub extends Base {
public Sub(String name, int age) {
//希望调用父类中的无参构造器
super("大黄", 45);
System.out.println("子类中的(String name,int age)被调用");
}
public Sub() {
super();
System.out.println("子类中的Sub()构造器被调用");
}
public Sub(String name) {
super("大狗", 30);
System.out.println("子类中的Sub(String name)构造器被调用");
}
public void sayOk() {//子类中的方法
System.out.println(n1 + " " + n2 + " " + n3);
test100();
test200();
test300();
//提供的特有方法去访问
System.out.println("n4" + getN4());
callTest400();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u9d2bc2u-1680138080442)(C:\Users\27310\AppData\Roaming\Typora\typora-user-images\image-20230130113634678.png)]
3、初始化的是两个参数的构造器
此时,调用了Sub的两个参数的构造器,这个构造器中,利用 super(“大黄”, 45)调用到了父类的两个参数的构造器,有参构造器顶替掉了无参构造器,所以系统不会调用Base的无参构造器
public class TextExtends02 {
public static void main(String[] args) {
Sub sub2 = new Sub("jack", 45);
}
}
class TopBase {//父类的父类的Object
public TopBase() {
System.out.println("构造器TopBase被调用");
}
}
class Base extends TopBase {
public Base() {
System.out.println("父类中的Base()构造器被调用...");
}
public Base(String name, int age) {
System.out.println("父类的Base(String name, int age)被调用");
}
public Base(String name) {
System.out.println("父类的Base(String name)被调用");
}
class Sub extends Base {
public Sub(String name, int age) {
//希望调用父类中的无参构造器
super("大黄", 45);
System.out.println("子类中的(String name,int age)被调用");
}
public Sub() {
super();
System.out.println("子类中的Sub()构造器被调用");
}
public Sub(String name) {
super("大狗", 30);
System.out.println("子类中的Sub(String name)构造器被调用");
}
public void sayOk() {//子类中的方法
System.out.println(n1 + " " + n2 + " " + n3);
test100();
test200();
test300();
//提供的特有方法去访问
System.out.println("n4" + getN4());
callTest400();
}
}
继承后,父类的属性和方法的访问
子类继承父类后,会继承父类所有的属性和方法,在访问时,子类可以直接访问父类非私有的属性和方法,私有的属性和方法需要通过调用父类提供的公开的方法进行访问
public class TextExtends02 {
public static void main(String[] args) {
Sub sub = new Sub();
sub.sayOk();
}
}
class Base extends TopBase {
//四个属性
public int n1 = 100;
protected int n2 = 200;
int n3 = 300;
private int n4 = 400;
//特有的方法
public int getN4() {
return n4;
}
public void test100() {
System.out.println("test100");
}
protected void test200() {
System.out.println("test200");
}
void test300() {
System.out.println("test300");
}
private void test400() {
System.out.println("test400");
}
//特有的方法
public void callTest400() {
test400();
}
}
class Sub extends Base {
public void sayOk() {//子类中的方法
System.out.println(n1 + " " + n2 + " " + n3);
test100();
test200();
test300();
//提供的特有方法去访问
System.out.println("n4" + getN4());
callTest400();
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EjkEa00q-1680138080443)(C:\Users\27310\AppData\Roaming\Typora\typora-user-images\image-20230130114635584.png)]
继承机制的本质
当子类调用属性或者方法时,按照查找关系返回信息
1、如果子类有该属性或者方法,如果子类有,并且可以直接访问,返回信息
2、如果子类没有这个属性,看父类有没有(父类有,并且可以直接访问,返回信息)
3、如果父类没有,按照 2 的规则继续寻找上级父类,直到Object
public class ExtendsTheory {
public static void main(String[] args) {
Son son = new Son();
System.out.println(son.name);
System.out.println(son.getAge());
System.out.println(son.hobby);
}
}
class GrandPa {//爷爷类
String name = "大头爷爷";
String hobby = "旅游";
}
class Father extends GrandPa {//父类
String name = "大头爸爸";
private int age = 37;
public int getAge() {
return age;
}
}
class Son extends Father {//子类
String name = "大头儿子";
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RnxeaG1j-1680138080443)(C:\Users\27310\AppData\Roaming\Typora\typora-user-images\image-20230130115249360.png)]
多态
1、方法的多态
重写和重载提现多态
重载:通过传入不同的参数,从而调用不同的方法
重写:调用不同类中的方法,实现不同的功能
public static void main(String[] args) {
//方法的重载体现多态
A a = new A();
//这里我们传入不同的参数,调用不同的sum方法,就体现多态
System.out.println(a.sum(10, 20));
System.out.println(a.sum(10, 20, 30));
a.say();
//方法的重写也体现了多态
B b = new B();
b.say();
}
}
class B {//父类
public void say() {
System.out.println("B类中的say()方法被调用");
}
}
class A extends B {//子类
public int sum(int n1, int n2) {
return n1 + n2;
}
public int sum(int n1, int n2, int n3) {
return n1 + n2 + n3;
}
public void say() {
System.out.println("A类中的say()方法被调用");
}
}
2、对象的多态
1、一个对象的编译类型和运行类型可以不一致
2、编译类型在定义对象的时候,就确定了,不能改变
3、运行类型是可以改变的
4、编译类型看=号的左边 运行类型看=号的右边
多态的注意事项和细节讨论
多态的前提是:两个对象(类存在继承关系)
多态的向上转型
本质:父类的引用指向了子类的对象
语法:父类类型 引用名 = new 子类类型();
特点:
1、可以调用父类的所有成员(访问权限)
2、不能调用子类的特有成员、因为在编译阶段能调用哪一些成员,是由编译类型决定的
3、最终的运行效果看子类(运行类型)的具体实现,
调用方法的时候,按照从子类(运行类型)开始查找方法,然后调用
public static void main(String[] args) {
Animal02 animal02 = new Cat02();
Object object = new Cat02();
animal02.run();
animal02.eat();
animal02.show();
animal02.sleep();
// animal02.catMouse();
}
}
class Animal02 {
String name = "动物";
int age = 10;
public void sleep() {
System.out.println("睡");
}
public void run() {
System.out.println("跑");
}
public void eat() {
System.out.println("吃");
}
public void show() {
System.out.println("hello 你好");
}
}
class Cat02 extends Animal02 {
public void eat() {
System.out.println("猫吃鱼的方法");
}
public void catMouse() {
System.out.println("猫抓老鼠");
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PANg87J8-1680138080444)(C:\Users\27310\AppData\Roaming\Typora\typora-user-images\image-20230201113359231.png)]
多态的向下转型(解决向上转型不能调用子类特有的方法)
调用子类特有的方法
语法:子类类型 引用名= (子类类型) 父类引用
1、只能强转父类的引用,不能强转父类的对象
2、父类的引用必须指向的是当前目标类型的对象
3、当向下转型后,可以调用子类类型中的所有成员
Animal02 animal02 = new Cat02();
// Cat02 cat02=(Cat02) animal02;
// cat02.catMouse();
//一步到位
((Cat02) animal02).catMouse();
}
}
class Animal02 {
String name = "动物";
int age = 10;
public void sleep() {
System.out.println("睡");
}
public void run() {
System.out.println("跑");
}
public void eat() {
System.out.println("吃");
}
public void show() {
System.out.println("hello 你好");
}
}
class Cat02 extends Animal02 {
public void eat() {
System.out.println("猫吃鱼的方法");
}
public void catMouse() {
System.out.println("猫抓老鼠");
}
}
class Dog02 extends Animal02 {
}
属性没有重写之说!属性值看编译类型
public class PolyDetail02 {
public static void main(String[] args) {
// 属性没有重写之说!属性的值看编译类型
Base base=new Sub();//向上转型
System.out.println(base.count);
Sub sub=new Sub();
System.out.println(sub.count);
}
}
class Base {
//父类
int count = 0;
}
class Sub extends Base {
//子类
int count = 20;
}
");
}
}
class Cat02 extends Animal02 {
public void eat() {
System.out.println(“猫吃鱼的方法”);
}
public void catMouse() {
System.out.println("猫抓老鼠");
}
}
class Dog02 extends Animal02 {
}
#### 属性没有重写之说!属性值看编译类型
```java
public class PolyDetail02 {
public static void main(String[] args) {
// 属性没有重写之说!属性的值看编译类型
Base base=new Sub();//向上转型
System.out.println(base.count);
Sub sub=new Sub();
System.out.println(sub.count);
}
}
class Base {
//父类
int count = 0;
}
class Sub extends Base {
//子类
int count = 20;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dgIyXazU-1680138080444)(C:\Users\27310\AppData\Roaming\Typora\typora-user-images\image-20230201114132466.png)]