面向对象的三特性
1. 封装
String name="da";
int age=3000;
char sex='男';
double score=15.6;
在对象的外部,为对象的属性赋值,可能存在非法数据的录入。所以我们要控制属性的赋值。
使用private封装属性,get、set获取、设置属性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s1glc8uK-1629479583906)(_v_images/20210812153937980_11156.png =496x)]
package work;
/**
* @Author night
* @Date 2021/8/12 11:32
*/
class Test {
public static void main(String[] args) {
Student student = new Student();
student.setAge(1500);
student.sex = 'y';
student.name = "da";
student.score = 99.5;
student.sayHi();
}
}
public class Student {
String name;
private int age;
char sex;
double score;
//默认构造方法
public Student() {
}
//age的get方法:获取age值
public int getAge() {
return age;
}
//age的set方法:设置age值
public void setAge(int age) {
//控制age的值
if (age > 0 && age <= 130) {
this.age = age;
} else {
this.age = 18;
}
}
//输出方法
public void sayHi() {
System.out.println("姓名:" + this.name + "年龄:" + this.age + "性别:"
+ this.sex + "分数:" + this.score);
}
}
使用private封装age属性,并且添加getAge、setAge方法用于获取、设置age的值,然后在setAge方法中对age的值进行控制。
案例:
需求:
实现银行功能
用户输入正确卡号和密码后可执行以下操作
菜单如下:1.存款2.取款3.转账4.查询余额5.修改密码0.退出
分析:
User类(cardNo、identity、username、password、phone、balance)
Bank类主要包括以下功能
初始化用户(initial)
用户登录(login)
显示菜单(showMenu)
存款(save)、取款(withDraw)、转账(trans)、查询余额(query)、修改密码(modifyPassword)
package work;
import java.util.Scanner;
/**
* @Author night
* @Date 2021/8/12 15:43
*/
class TestCard {
public static void main(String[] args) {
Card card = new Card();
card.initial();
}
}
public class Card {
/**
* 卡号、身份证号码、姓名、密码、联系方式、余额
*/
private String cardNo;
private String identity;
private String username;
private String password;
private String phono;
private double balance;
//因为经常使用,直接创建实例变量,在全局中都可以使用
Scanner scanner = new Scanner(System.in);
public void initial() {
System.out.println("开始注册用户信息:");
System.out.print("请输入姓名:");
username = scanner.next();
System.out.print("请输入密码:");
password = scanner.next();
System.out.print("请输入身份证号码:");
identity = scanner.next();
System.out.print("请输入联系方式:");
phono = scanner.next();
System.out.print("请输入银行卡号:");
cardNo = scanner.next();
System.out.print("请输入余额:");
balance = scanner.nextDouble();
System.out.println("********用户信息如下********");
System.out.println("姓名:" + username + "\t\t" + "密码:" + password + "\t\t" + "身份证号码:" + identity);
System.out.println("联系方式:" + password + "\t\t" + "卡号:" + cardNo + "\t\t" + "余额:" + balance);
login();
}
/**
* 登录方法
*/
public void login() {
String name;
String pwd;
System.out.println("********请登录********");
System.out.print("请输入姓名:");
name = scanner.next();
System.out.print("请输入密码:");
pwd = scanner.next();
//校验密码是否正确
if (name.equals(username) && pwd.equals(password)) {
System.out.println("********登录成功,欢迎你********");
showMenu();
} else {
System.out.println("********登录失败,请重新登录********");
login();
}
}
//显示菜单方法
public void showMenu() {
System.out.println("1、存款 2、取款 3、转账 4、余额查询 5、修改密码 0、退出");
int choose;
System.out.print("请选择业务:");
choose = scanner.nextInt();
switch (choose) {
case 1:
System.out.println("********进入存款********");
save();
break;
case 2:
System.out.println("********进入取款********");
withDraw();
break;
case 3:
System.out.println("********进入转账********");
trans();
break;
case 4:
System.out.println("********查询余额********");
query();
break;
case 5:
System.out.println("********修改密码********");
modifyPassword();
break;
case 0:
return;
}
}
//存款方法
public void save() {
System.out.print("请输入存进的金额:");
int money = scanner.nextInt();
balance = balance + money;
System.out.print("您的余额:" + balance);
System.out.println();
showMenu();
}
//取款方法
public void withDraw() {
System.out.print("请输入取出的金额:");
int money = scanner.nextInt();
//取款数大于余额无法取款
if (money > balance) {
System.out.println("余额不足,请重新输入");
withDraw();
}
balance = balance - money;
System.out.print("您的余额:" + balance);
System.out.println();
showMenu();
}
//转账
public void trans() {
System.out.print("请输入转入的卡号:");
String orderCardNo = scanner.next();
//自己不能向自己的卡内转账
if (orderCardNo.equals(cardNo)) {
System.out.println("自己不能向自己的卡内转账");
trans();
}
System.out.print("请输入转入的金额:");
double money = scanner.nextDouble();
//转账数大于余额无法转账
if (money > balance) {
System.out.println("余额不足,请重新输入");
trans();
}
balance = balance - money;
System.out.print("您已向卡号为:" + orderCardNo + "转入" + money + "您卡内余额为" + balance);
System.out.println();
showMenu();
}
public void query() {
System.out.print("您的余额:" + balance);
System.out.println();
showMenu();
}
String pwd1 = null;
public void modifyPassword() {
System.out.println("请输入密码:");
pwd1 = scanner.next();
System.out.println("请确认密码:");
String pwd2 = scanner.next();
//校验两次输入的密码是否相同
if (pwd1.equals(pwd2)) {
password = pwd1;
} else {
System.out.println("两次密码输入不一致,请重新输入:");
modifyPassword();
}
System.out.print("该账号的密码:" + password);
System.out.println();
showMenu();
}
//无参构造方法
public Card() {
}
//get and set
public String getCardNo() {
return cardNo;
}
public void setCardNo(String cardNo) {
this.cardNo = cardNo;
}
public String getIdentity() {
return identity;
}
public void setIdentity(String identity) {
this.identity = identity;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhono() {
return phono;
}
public void setPhono(String phono) {
this.phono = phono;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
2. 访问修饰符
本类 | 同包 | 非同包子类 | 其它 | |
---|---|---|---|---|
private | √ | × | × | × |
default | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
3. 继承
子类继承父类后,子类可以使用父类中的属性和方法,也可定义子类独有的属性和方法。
语法:
class子类extends父类{}/∥定义子类时,显示继承父类
public class inherit {
public static void main(String[] args) {
//实例化子类
Dog dog = new Dog();
//子类通过继承调用父类的属性,从而给自己赋值
dog.name = "狗";
dog.age = 2;
dog.sex = "公";
dog.hairColor="白色";
System.out.println(dog.name+dog.hairColor+dog.sex+dog.age);
//调用子类特有的方法
dog.run();
//子类调用父类的方法
dog.eat();
dog.sleep();
}
}
//父类
class Animal {
public String name;
public int age;
public String sex;
public void eat() {
System.out.println("吃.....");
}
public void sleep() {
System.out.println("睡.....");
}
}
//子类使用extends继承父类
class Dog extends Animal {
public String hairColor;
//子类特有的方法
public void run() {
System.out.println("跑.....");
}
}
不可继承
构造方法:
类中的构造方法,只负责创建本类对象,不可继承。
private修饰的属性和方法:(权限不足)
访问修饰符的一种,仅本类可见。
父子类不在同一个package中时,default修饰的属性和方法:(权限不足)
访问修饰符的一种,仅同包可见。
4. 方法覆盖
方法覆盖原则:
方法名称、参数列表、返回值类型必须与父类相同。
访问修饰符不能比父类更严格。
方法覆盖的执行:
子类覆盖父类方法后,调用时优先执行子类覆盖后的方法。
public class inherit {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
}
}
//父类
class Animal {
public String name;
public int age;
public String sex;
public void eat() {
System.out.println("吃.....");
}
public void sleep() {
System.out.println("睡.....");
}
}
//子类
class Dog extends Animal {
//重写父类eat方法
@Override
public void eat() {
System.out.println("吃狗粮");
}
//子类特有方法
public void run() {
System.out.println("跑.....");
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RsoWF1bJ-1629479583908)(_v_images/20210813090902401_6814.png =495x)]
super关键字
在子类中,可直接访问从父类继承到的属性和方法,但如果父子类的属性或方法存在重名(属性遮蔽、方法覆盖)时,需要加以区分,才可专项访问。
当子类继承父类,子类想要使用父类方法里面的方法体,可以使用super关键字完成
示例:
Father类的show方法输出Father,Son类的show方法输出Son,如果实例化Son调用show方法并且想输出Father,就需要使用super.show();,这里的show方法调用的就是Father类的show方法
public class superInherit {
public static void main(String[] args) {
Son son = new Son();
son.show();
}
}
//父类
class Father {
public void show() {
System.out.println("Father");
}
}
//子类
class Son extends Father {
public void show() {
//调用父类的show方法
super.show();
System.out.println("Son");
}
}
不仅可以调用方法,还可以调用属性。
public class superInherit {
public static void main(String[] args) {
Son son = new Son();
son.print();
}
}
//父类
class Father {
int age = 10;
}
//子类
class Son extends Father {
int age = 20;
public void print() {
int age = 30;
System.out.println("局部变量:" + age);
System.out.println("实例变量:" + this.age);
System.out.println("父类变量:" + super.age);
}
}
super还可以调用父类的无参构造方法
public class superInherit {
public static void main(String[] args) {
Son son = new Son();
son.print();
}
}
//父类
class Father {
public Father() {
System.out.println("父类默认构造方法");
}
}
//子类
class Son extends Father {
public Son() {
//调用父类默认构造方法
super();
System.out.println("子类默认构造方法");
}
public void print() {
System.out.println("子类特有方法");
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D5hWJ3tG-1629479583909)(_v_images/20210813094815662_20472.png =480x)]
在子类中使用super();可以调用父类默认的构造方法,调用时必须放在第一行,和this一样。
程序执行顺序是:父类构造方法、子类构造方法、子类特有方法
子类还可以调用父类带参的构造方法
public class superInherit {
public static void main(String[] args) {
//实例化子类,并且调用的是带参构造方法,不是默认的无参构造方法
Son son = new Son(100, 200, 300);
son.print();
}
}
//父类
class Father {
int num1;
int num2;
public Father() {
System.out.println("父类默认构造方法");
}
//父类重载自己的构造方法:两个参数
public Father(int num1, int num2) {
this.num1 = num1;
this.num2 = num2;
System.out.println(num1 + "\t" + num2);
}
}
//子类
class Son extends Father {
int num3;
//子类重载自己的构造方法
public Son(int num1, int num2, int num3) {
//调用父类的带参构造方法
super(num1, num2);
this.num3 = num3;
System.out.println(num1 + "\t" + num2 + "\t" + num3);
}
public Son() {
//调用父类默认构造方法
super();
System.out.println("子类默认构造方法");
}
public void print() {
System.out.println("子类特有方法");
}
}
this和super的区别
this表示当前对象引用,调用本类(包括继承)的属性、方法、本类构造方法
super表示父类对象引用,调用父类的属性、方法、构造方法
this和super不能同时使用,因为两个都必须在首行
public class superInherit {
public static void main(String[] args) {
//实例化子类,并且调用的是带参构造方法,不是默认的无参构造方法
new Son(10);
}
}
//父类
class Father {
public Father() {
System.out.println("父类默认构造方法");
}
}
//子类
class Son extends Father {
//子类重载自己的构造方法
public Son(int num1) {
this();
System.out.println(num1);
}
public Son() {
//调用父类默认构造方法
super();
System.out.println("子类默认构造方法");
}
}
执行流程:当实例化子类特有方法时,首先调用子类特有的方法,子类特有方法第一行是this();所以会去调用子类的无参构造方法,子类的无参构造方法第一行是super();所以调用父类的无参构造方法,父类的无参构造方法输出:父类默认构造方法,执行结束后掉头到子类无参构造方法执行输出:子类默认构造方法,执行结束后再掉头到子类带参构造方法,因为主方法在实例化是传入参数10,所以现在带参构造方法的num1=10,程序执行输出10。
5. 多态
概念:父类引用指向子类对象,从而产生多种形态。
多态:二者具有直接或间接的继承关系时,父类引用可指向子类对象
public class Polymorphism {
public static void main(String[] args) {
//向上转型
Animal animal = new Dog();
animal.age = 2;
animal.bread = "金毛";
animal.sex = "公";
animal.eat();
System.out.println(animal.sex + animal.bread + animal.sex);
//向下转型
((Dog) animal).run();
((Dog) animal).furColor = "白色";
System.out.println(((Dog) animal).furColor);
}
}
class Animal {
String bread;
int age;
String sex;
public void eat() {
System.out.println("吃......");
}
}
class Dog extends Animal {
String furColor;
public void eat() {
System.out.println("吃狗粮");
}
public void run() {
System.out.println("跑......");
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R1w1NugH-1629479583912)(_v_images/20210813110458033_13396.png =280x)]
多态的应用
场景一:
使用父类作为方法形参实现多态,使方法参数的类型更为宽泛。
public class Polymorphism {
public static void main(String[] args) {
Master master = new Master();
master.name = "jack";
//master.feed(new Dog());
Dog dog = new Dog();
master.feed(dog);
}
}
//主人类
class Master {
String name;
//将动物类直接作为参数
public void feed(Animal animal) {
System.out.println(name + "喂食");
//调用eat方法,至于是谁的eat就需要看feed从参数是谁,如果是dog就是dog的feed方法
animal.eat();
}
}
//动物类:父类
class Animal {
public void eat() {
System.out.println("吃......");
}
}
//狗狗类:子类
class Dog extends Animal {
public void eat() {
System.out.println("狗狗开始吃狗粮");
}
}
场景二:使用父类作为方法返回值实现多态,使方法可以返回不同子类对象
public class Polymorphism {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int choose = scanner.nextInt();
Master master = new Master();
//choose通过buy方法赋值type=choose,if会选择type实现实例化不同的子类。
// 如tyepe是1就会实例化 Animal animal =new Dog();然后返回给return animal;(返回的是类型,不是1)
// 在通过if判断是否是空。。。
Master.Animal animal = master.buy(choose);
if (animal != null) {
System.out.println("购买成功");
//animal不是空,通过instanceof判断animal类型
if (animal instanceof Master.Dog) {
//将animal赋值给dog,现在程序想调用子类方法,但是dog是Dog类,animal是Animal类,所以需要强转
Master.Dog dog = (Master.Dog) animal;
//调用Dog的eat();
dog.eat();
} else if (animal instanceof Master.Bird) {
Master.Bird bird = (Master.Bird) animal;
bird.eat();
}
} else {
System.out.println("购物失败");
}
}
}
//主人类
class Master {
public Animal buy(int type) {
Animal animal = null;
if (type == 1) {
animal = new Dog();
} else if (type == 2) {
animal = new Bird();
}
return animal;
}
//动物类:父类
class Animal {
public void eat() {
System.out.println("吃......");
}
}
//狗狗类:子类
class Dog extends Animal {
public void eat() {
System.out.println("狗狗开始吃狗粮");
}
}
class Bird extends Animal {
public void eat() {
System.out.println("鸟开始吃虫子");
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xbtTIj01-1629479583913)(_v_images/20210813115140776_967.png =370x)]
instanceof关键字
判读对象的数据类型,返回booolean类型结果
语法:
类型A instanceof 类型B
示例:判断animal是不是Bird类型
if (animal instanceof Bird) {}
6. 总结
继承:子类继承父类,可以使用父类的方法和属性
重写:子类继承父类,子类可以有自己的特有方法、属性,也可以调用父类的方法、属性。子类指向自己:Dog dog=new Dog();
多态:父类引用指向子类对象,从而产生多种形态。
子类继承父类,子类可以有自己的特有方法、属性。父类指向子类:Animal animal=new Dog();
向上转型:父类调用子类和自己共有的方法。自动类型转换Animal animal=new Dog(); animal.eat();
向下转型:父类调用子类特有的方法。强制类型转换:Animal animal=new Dog(); ((Dog) animal).run();
两种应用场景
1、使用父类作为方法形参,实现多态
2、使用父类作为方法返回值,实现多态
作用
1、屏蔽子类间的差异
2、灵活、耦合度低
d extends Animal {
public void eat() {
System.out.println(“鸟开始吃虫子”);
}
}
}
[外链图片转存中...(img-xbtTIj01-1629479583913)]
#### instanceof关键字
判读对象的数据类型,返回booolean类型结果
语法:
类型A instanceof 类型B
示例:判断animal是不是Bird类型
`if (animal instanceof Bird) {}`
## 6. 总结
继承:子类继承父类,可以使用父类的方法和属性
重写:子类继承父类,子类可以有自己的特有方法、属性,也可以调用父类的方法、属性。子类指向自己:Dog dog=new Dog();
多态:父类引用指向子类对象,从而产生多种形态。
子类继承父类,子类可以有自己的特有方法、属性。父类指向子类:Animal animal=new Dog();
向上转型:父类调用子类和自己共有的方法。自动类型转换Animal animal=new Dog(); animal.eat();
向下转型:父类调用子类特有的方法。强制类型转换:Animal animal=new Dog(); ((Dog) animal).run();
两种应用场景
1、使用父类作为方法形参,实现多态
2、使用父类作为方法返回值,实现多态
作用
1、屏蔽子类间的差异
2、灵活、耦合度低