一、封装
1.1 为什么要封装
-
有些数据语法上是可以的,在生产中是非法的
- 年龄20000
- 工资-10000
1.2 封装的流程
1、私有化属性【private】
2、提供公开的setXxx和getXxx方法
3、在方法中制定访问规则
1.3 封装案例
Student
package com.shine.private0;
/**
* 类名
* Student
* 属性
* 学号
* 姓名
* 年龄
* 信息
* 方法
* 展示
*/
public class Student {
// 属性
String stuNo;
String name;
// 私有的属性,只能在当前类中使用
private int age;
String info;
/**
* 读取数据
* @return
*/
public int getAge() {
return age;
}
/**
* 设置数据
* @param age
*/
public void setAge(int age) {
// 过滤非法数据
if (age>0 && age<130) {
this.age = age;
} else {
System.err.println("非法年龄:" + age);
this.age = -1; // 尝试设置非法的年龄,把年龄设置为-1
}
}
public void show() {
System.out.println("Student [stuNo=" + stuNo + ", name=" + name + ", age=" + age + ", info=" + info + "]");
}
}
TestStudent
package com.shine.private0;
public class TestStudent {
public static void main(String[] args) {
// 创建对象
Student stu = new Student();
// 属性赋值
stu.stuNo = "20191012066";
stu.name = "张三";
//stu.age = 22; // 私有的属性不能再类的外部直接访问
stu.info = "法外狂徒";
stu.setAge(22);
System.out.println(stu.getAge());
// 调用方法展示信息
stu.show();
// 修改属性
//stu.age = 233;
stu.setAge(233);
stu.show();
}
}
Phone
package com.shine.private0;
public class Phone {
// 属性
private String brand;
private String model;
private String color;
private double price;
private String info;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
String[] brands = {"苹果","三星","华为","中兴","联想","摩托罗拉"};
this.brand = "不存在";
for (int i = 0; i < brands.length; i++) {
if (brand.equals(brands[i])) {
this.brand = brand;
break;
}
}
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
if (price>0 && price<1000000) {
this.price = price;
} else {
this.price = -1;
}
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
二、继承
2.1 概述
生活中的继承
- 后辈从先辈那里继承得到财、物
- 后辈从先辈获取基因
程序中的继承
- 子类获取到父类中的属性和方法
2.2 继承语法
class A{}
class B extends A{}
class C extends B{}
B能得到A中的属性和方法
C得到A和B中的属性和方法
Java是单继承,Java支持多级继承
2.3 继承入门案例
- 动物世界
package com.shine.extends0;
public class Demo01 {
public static void main(String[] args) {
/**
* 编写代码展示动物世界中的动物
*/
// 创建对象
Lion lion = new Lion();
Ratel ratel = new Ratel();
TheHyena hyena = new TheHyena();
}
}
/**
* 狮子类
*/
class Lion{
String breed;
String name;
int age;
String sex;
String color;
String weight;
double height;
double length;
public void eat() {
}
public void sleep() {
}
public void hunt() {
}
}
/**
* 羊驼
*/
class Alpaca{
String breed;
String name;
int age;
String sex;
String color;
String weight;
double height;
double length;
public void eat() {
}
public void sleep() {
}
public void climbTree() {
}
public void run() {
}
}
/**
* 鳄鱼
*/
class Crocodile {
String breed;
String name;
int age;
String sex;
String color;
String weight;
double height;
double length;
public void eat() {
}
public void sleep() {
}
public void swim() {
}
public void climb() {
}
}
/**
* 蓝鹤
*/
class BlueCrane{
String breed;
String name;
int age;
String sex;
String color;
String weight;
double height;
double length;
public void eat() {
}
public void sleep() {
}
public void fly() {
}
}
/**
* 所有动物中抽取共性的属性和方法,形成Animal这个类
*/
class Animal {
String breed;
String name;
int age;
String sex;
String color;
String weight;
double length;
public void eat() {
}
public void sleep() {
}
}
class Ratel {
}
class TheHyena extends Animal{
double height;
public void hunt() {
}
public void run() {
}
}
2.4 继承案例
Worker
package com.shine.extends0;
/**
* 类名
* 工人
* 属性
* 种类
* 姓名
* 年龄
* 工资
* 信息
* 方法
* 吃饭
* 睡觉
* 工作
*/
public class Worker {
String type;
String name;
int age;
double salary;
String info;
public void eat() {
System.out.println("工人需要吃饭");
}
public void sleep() {
System.out.println("工人需要睡觉");
}
public void work() {
System.out.println("工人需要工作");
}
}
Cook
package com.shine.extends0;
/**
* 类名
* 厨师
* 继承Worker,得到属性和方法
*/
public class Cook extends Worker{
// 属性
// 方法
public void cook() {
System.out.println("厨师做饭");
}
public void teastFood() {
System.out.println("厨师需要试菜");
}
}
2.5 不可继承
父类中的构造方法
- 构造方法只负责本类类型对象的创建
父类中私有的属性和方法
- 受访问权限修饰符限制,访问范围只能在当前类中
三、访问修饰符
3.1 概述
- 修饰属性、方法、类的修饰符
- 限制数据在不同位置的可见性
3.2 修饰符和范围
3.3 案例代码
modify01.FFF
package com.shine.modify01;
public class FFF {
public String publicStr = "publicStr";
protected String protectedStr = "protectedStr";
String defaultStr = "defaultStr";
private String privateStr = "privateStr";
/**
* 在同类中能访问的内容:
* public
* protected
* default
* private
*/
public void show() {
System.out.println(publicStr);
System.out.println(protectedStr);
System.out.println(defaultStr);
System.out.println(privateStr);
}
}
modify01.Demo01
package com.shine.modify01;
public class Demo01 {
public static void main(String[] args) {
/**
* public
* protected
* default
* private
*/
// 创建对象
FFF fff = new FFF();
/**
* 同一个包中能访问:
* public
* protected
* default
*/
System.out.println(fff.publicStr);
System.out.println(fff.protectedStr);
System.out.println(fff.defaultStr);
// System.out.println(fff.privateStr);
}
}
modify02.SSS
package com.shine.modify02;
import com.shine.modify01.FFF;
/**
* FFF的子类
*/
public class SSS extends FFF {
/**
* 在不同包子类中能访问的内容:
* public
* protected
*/
public void show() {
System.out.println(publicStr);
System.out.println(protectedStr);
// System.out.println(defaultStr);
// System.out.println(privateStr);
}
}
modify02.Demo02
package com.shine.modify02;
import com.shine.modify01.FFF;
public class Demo02 {
public static void main(String[] args) {
// 创建对象
FFF fff = new FFF();
/**
* 同其他位置能访问:
* public
*/
System.out.println(fff.publicStr);
// System.out.println(fff.protectedStr);
// System.out.println(fff.defaultStr);
// System.out.println(fff.privateStr);
}
}
四、方法重写
4.1 概述
-
子类从父类中继承得到的方法不一定能满足需求
-
可以在子类中定义和父类中【几乎】相同的方法:
- 方法的声明部分相同
- 方法体不同,可以根据子类需要重写方法体
4.2 重写注意事项
- 重写可以使用override标注
- 重写的方法参数列表、返回值类型必须和父类中相同
- 重写方法的访问修饰符范围要大于等于父类方法的修饰符
- 优先使用被重写的方法
4.3 代码
Worker
package com.shine.override;
/**
* 类名
* 工人
* 方法
* 工作
*/
public class Worker {
void work() {
System.out.println("工人需要工作");
}
}
Cook
package com.shine.override;
/**
* 类名
* 厨师
* 继承Worker,得到属性和方法
*/
public class Cook extends Worker{
@Override
void work() {
System.out.println("厨师的工作是切墩和颠勺");
}
}
Driver
package com.shine.override;
/**
* 类名
* 司机
* 继承了Worker
*/
public class Driver extends Worker{
@Override
public void work() {
System.out.println("司机的工作是开车");
}
public void work(String info) {
System.out.println("司机的工作是" + info);
}
}
TestWorker
package com.shine.override;
public class TestWorker {
public static void main(String[] args) {
// 工人对象
Worker worker = new Worker();
worker.work();
// 厨师对象
Cook cook = new Cook();
// 使用子类重写之后的方法
cook.work();
// 司机对象
Driver driver = new Driver();
// 使用子类重写之后的方法
driver.work();
}
}
五、super
5.1 概述
-
如果子类中存在和父类中重名的属性和方法
-
子类中的属性和方法会屏蔽父类中的属性和方法
-
如果明确表示调用父类中的属性和方法?
- 使用super来明确表示调用父类中的内容
5.2 super的使用
调用父类中的属性
super.属性
调用父类中的方法
super.方法(参数)
调用父类中的构造器
super(参数)
父类
package com.shine.super0;
public class WeChatV1 {
String name;
String info;
String version = "Version 1.0";
public WeChatV1() {
super();
}
public WeChatV1(String name, String info, String version) {
super();
this.name = name;
this.info = info;
this.version = version;
}
public void chat() {
System.out.println("微信第一版,能使用流量发送免费文字信息");
}
}
子类
package com.shine.super0;
public class WeChatV2 extends WeChatV1{
String version = "Version 2.0";
public WeChatV2() {
this("", "", "");
}
public WeChatV2(String name, String info, String version) {
super(name, info, version); // 调用父类中的构造方法,必须放在构造方法的第一行
}
@Override
public void chat() {
super.chat(); // 调用父类中的实例方法
System.out.println("微信第2版,能发送图片和语音消息");
}
public void show() {
// 输出子类和父类中的属性
String version = "Version 2.1";
System.out.println(version); // 局部变量
System.out.println(this.version); // 实例变量
System.out.println(super.version); // 父类中的实例变量
}
}
测试
package com.shine.super0;
public class Demo01 {
public static void main(String[] args) {
/**
* 父类
* 属性
* 方法
* 构造器
* 子类
* 属性
* 方法
* 构造器
*/
WeChatV2 chatV2 = new WeChatV2();
chatV2.chat();
}
}
5.3 子类对象创建过程
-
创建子类对象之前需要先创建父类对象
-
有父类的属性和方法 + 子类的属性和方法,构成子类的对象
- 默认调用父类的无参数构造方法,可以省略调用的代码
5.4 super调用构造器
调用无参数构造器
- 在创建子类对象过程中默认调用父类中的无参数构造方法
调用有参数构造器
- 如果父类中没有无参数构造方法,子类必须显示调