高内聚,低耦合
多聚合,少继承
1、目标
理解封装的作用
会使用封装
会使用java中的包组织类
掌握访问修饰符、理解访问权限
2、封装
2.1 为什么使用封装
解决程序设计上的缺陷:
使用封装 来解决该问题。
2.2 什么是封装
面向对象三大特征之一 ——封装
概念:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问
把尽可能多的东西藏起来,对外提供便捷的接口。
说白了就是把对象中的属性信息封装在对象类内部,不让用户直接使用类属性进行访问,而是定义一个方法作为类属性的接口提供给用户访问使用。
封装的两个大致原则
把所有的属性藏起来
把尽可能多的东西藏起来,对外提供便捷的接口。
2.3 如何使用封装
步骤:
修改属性的可见性,设为private
创建getter/setter方法,用于属性的读写
在getter/setter方法中加入属性控制语句,对属性值的合法性进行判断
idea快捷键:alt + insert
2.4 封装的好处
便于使用者正确使用系统,防止错误修改属性
有助于系统之间的松耦合,提高系统独立性
提高软件的可重用性
降低了构建大型系统的风险
3、包
包的层级使用 . 符号
package当前类位于哪个包下(package必须在代码第一行)
import引入包(包名.类名)可以使用* 但是不推荐
规范:
网络项目(com、cn、net.公司名.项目名.模块名
com.hz.shop.test01
3.1 为什么需要包:
在做项目的时候,我们会创建很多类,为了避免类名相同导致编译器无法正确识别类,所以引用了包,以便更好地区分类。
Windows树形文件系统:文档分门别类,易于查找和管理 使用目录解决文件同名冲突问题
3.2 包的作用
允许类组成较小的单元(类似文件夹),易于找到和使用相应的文件
防止命名冲突区分名字相同的类
有助于实施访问权限控制
3.3 如何创建包
作为Java源代码第一条语句
用package声明包,以分号结尾
可以使用语句 package 路径1.路径2.
包命名规范
包名由小写字母组成,不能以圆点开头或结尾
package mypackage;
包名之前最好加上唯一的前缀,通常使用组织倒置的网络域名
package net.javagroup.mypackage;
包名后续部分依不同机构内部的规范不同而不同
package net.javagroup.research.powerproject;
3.4 idea创建包
JDK提供基本包:
java.lang:虚拟机自动引入
java.util:提供一些实用类
java.io:输入、输出
使用idea创建包的两种方法:
右键项目文件夹,选择package
3.5 如何导入包
为了使用不在同一包中的类。需要在java程序中使用import关键字导入这个类
import 包名.类名;
1、系统包。java.util
2、自定义包。cn.jtest.classan
*;指保重的所有类
School;指保重的School类
3.6 使用包的注意事项
一个类同时引用了两个来自不同包的同名类
必须通过完整类名来区分
每个包都是独立的,顶层包不会包含子包的类
package和import的顺序都是固定的
package必须位于第一行(忽略注释行)
只允许有一个package语句
其次是import
接着是类的声明
4、访问权限控制
类的访问控制和类成员的访问控制
4.1 类的访问修饰
类的访问修饰符:
public修饰符:公有访问级别
默认修饰符:包级私有访问级别
4.2 类成员的访问修饰符
作用域 修饰符 | 同一个类中 | 同一个包中 | 子类中 | 任何地方 |
private | 可以 | 不可以 | 不可以 | 不可以 |
默认修饰符 | 可以 | 可以 | 不可以 | 不可以 |
protected | 可以 | 可以 | 可以 | 不可以 |
public | 可以 | 可以 | 可以 | 可以 |
4.2.1 static修饰符
static可以用来修饰
成员变量
静态变量:可以直接通过类名访问
成员方法:
静态方法,可以直接通过类名访问
代码块
静态代码块,当java虚拟机加载类时,就会执行该代码块
static代码块
JVM加载类时,加载静态代码块
如果有多个静态块,按顺序加载
每个静态代码块只会被执行一次
public class StaticTest {
static int num=100;
static{
num+=100;
System.out.println(num);
}
static{
num+=100;
System.out.println(num);
}
}
StaticTest st1=new StaticTest();
StaticTest st2=new StaticTest();
System.out.println(StaticTest.num);
这里new对象之后会报错。这是因为 在对象的Class中只存在static静态变量,这里再new一个对象就多余了
类的成员变量包括
类变量(静态变量)
被static修饰的变量
在内存中只有一个拷贝
类内部,可在任何方法内直接访问静态变量
在其他类中,可以直接通过类名访问
实例变量
没有被static修饰的变量
每创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响
static变量的作用:
(1)能被类的所有实例共享,可作为实例之间进行交流的共享数据
(2)如果类的所有实例都包含一个相同的常量属性,可把这个属性定义为静态常量类型,从而节省内存空间
static变量是共享的变量,当实例化多个带有相同static变量的对象时,他们会共用这个static变量,改变其中一个static变量的值,其他实例化对象中的该static变量都会被改变
static方法:
静态方法:可以直接通过类名访问
静态代码块:只加载一次
static {
代码块
}
不能直接访问所属类的实例变量和实例方法
可直接访问类的静态变量和静态方法
实例方法:通过实例访问
可直接访问所属类的静态变量、静态方法、实例变量和实例方法
静态方法必须被实现 main()就是最常用的静态方法。
常见错误:
在实例方法里不可以定义static变量。
5、继承
继承是java中实现代码重用的重要手段之一。java中只支持单根继承,即一个类中鞥有一个直接父类
5.1 如何使用继承
使用继承:
使用extends关键字
编写父类
[访问修饰符] class Pet{
//公共属性和方法
}
编写子类,继承父类
[访问修饰符] class Dog extends Pet {
//子类特有的属性和方法
}
继承是Java中实现代码重用的重要手段之一。Java中只支持单根继承,即一个类只能有一个直接父类
单根继承
子类可以调用父类的属性和方法
父类调用不到子类独有的属性和方法
子类构造方法默认调用父类的无参构造方法(第一行默认调用)
5.2 理解继承
子类访问父类成员
(1)使用super关键字,super代表父类对象
(2)在子类构造方法中调用且必须是第一句
(3)不可以访问父类中定义为private的属性和方法
super关键字
1、构造方法 super() 必须在子类构造方法的第一行
2、调用属性 super.属性名 子类调用父类属性(父类属性不能是private)
3、调用方法 super.方法名() 子类调用父类的方法(不能是private)
访问父类构造方法
super();
super(name);
访问父类属性
super.name;
访问父类方法
super.print();
super关键字来访问父类的成员
super只能出现在子类的方法和构造方法中
super调用构造方法时,只能是第一句
super不能访问父类的private成员
5.3 继承条件下的构造方法
继承条件下构造方法的调用规则
子类构造方法没有通过super显示调用父类的有参构造方法,也没有通过this显示调用自身其他的构造方法
系统默认调用父类的无参构造方法
子类构造方法通过super显示调用父类的有参构造方法
执行父类相应构造方法,而不执行父类无参构造方法
子类构造方法通过this显示调用自身的其他构造方法,在相应构造方法中应用以上两条规则
5.4 理解继承
子类可以继承父类的什么资源
public和protected修饰的属性和方法,不管子类和父类是否在同一个包里
继承默认权限修饰符修饰的属性和方法,但子类和父类必须在同一个包里。
子类不能继承父类的什么资源
private成员
子类与父类不在同包,使用默认访问权限的成员
构造方法
访问修饰符protected
可以修饰属性和方法
本类、同包、子类可以访问
练习
练习一、使用封装实现企鹅类
Test
package exercise01;
import java.util.Scanner;
public class Test {
//需求说明
//使用封装实现电子宠物系统的企鹅类正确输入健康值和亲密度
//保证健康值的有效性(0-100),否则取默认值60
//保证亲密度的有效性(0-100),否则取默认值60
public static void main(String[] args) {
Penguin p =new Penguin();
Scanner sc = new Scanner(System.in);
System.out.println("请输入要领养的动物名字:");
p.setName(sc.next());
System.out.println("请输入要领养的动物类型:(1、狗狗 2、企鹅)");
p.setType(sc.nextInt());
System.out.println("请输入要领养的动物性别:(1、Q仔 2、Q妹)");
p.setSex(sc.nextInt());
System.out.println("请输入要领养的动物健康值:(1-100之间)");
p.setHealth(sc.nextInt());
System.out.println("自白");
System.out.println("我的名字是:" + p.getName() + "我是一只" + p.getType() + "我的性别是" + p.getSex() + "我的健康值是" + p.getHealth());
}
}
Penguin
package exercise01;
public class Penguin {
private String name;
private String type;
private String sex;
private int health;
public Penguin() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(int type) {
if (type == 1){
this.type = "狗狗";
}else{
this.type = "企鹅";
}
}
public String getSex() {
return sex;
}
public void setSex(int sex) {
if (sex == 1){
this.sex = "Q仔";
}else{
this.sex = "Q妹";
}
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
if(health < 0 || health > 100){
System.out.println("健康值应该在0-100之间,默认值为60");
this.health = 60;
}else{
this.health = health;
}
}
}
练习二、
模拟实现选民投票过程:一群选民进行投票,每个选民只允许投一次票,并且当投票总数达到100时,就停止投票
people
package exercise02;
public class people {
private String name;
static int num;
static final int MAX_NUM = 100;
public people() {
}
public people(String name) {
this.name = name;
}
public void toupiao(){
if (num == MAX_NUM){
System.out.println("投票已经结束");
}else{
System.out.println(this.name + "感谢您的投票");
num++;
}
}
}
Test
package exercise02;
import exercise02.people;
public class Test {
public static void main(String[] args) {
for (int i = 0;i<200;i++){
people p = new people("选民" +(i+1));
if (people.num == 100){
break;
}
p.toupiao();
}
}
}
作业
作业一
1.某公司要开发新游戏,请用面向对象的思想,设计游戏中的蛇怪和蜈蚣精
设定
1)蛇怪类:
属性包括:怪物名字,生命值,攻击力
方法包括:攻击,移动(曲线移动),补血(当生命值<10时,可以补加20生命值)
2)蜈蚣精类:
属性包括:怪物名字,生命值,攻击力
方法包括:攻击,移动(飞行移动)
要求
1)分析蛇怪和蜈蚣精的公共成员,提取出父类—怪物类
2)利用继承机制,实现蛇怪类和蜈蚣精类
3)攻击方法,描述攻击状态。内容包括怪物名字,生命值,攻击力
4)编写测试类,分别测试蛇怪和蜈蚣精的对象及相关方法
Monster
package homework01;
public class Monster {
//公共成员
private String Name;
private int Hp;
private int Atk;
public Monster() {
}
public Monster(String name, int hp, int atk) {
Name = name;
Hp = hp;
Atk = atk;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public int getHp() {
return Hp;
}
public void setHp(int hp) {
Hp = hp;
}
public int getAtk() {
return Atk;
}
public void setAtk(int atk) {
Atk = atk;
}
public void hate(){
System.out.println("怪物:" + Name + ",生命值:" + Hp + ",攻击力" + Atk);
}
}
Snake
package homework01;
public class Snake extends Monster{
public Snake() {
}
public Snake(String name, int hp, int atk) {
super(name, hp, atk);
}
public void Shate(){
super.hate();
}
public void move() {
System.out.println("曲线移动");
}
public void healing(){
if(getHp()<10){
setHp(getHp()+25);
}else if(getHp()+5>=100){
setHp(100);
}else {
setHp(getHp()+5);
}
}
}
Centipede
package homework01;
public class Centipede extends Monster {
public Centipede() {
}
public Centipede(String name, int hp, int atk) {
super(name, hp, atk);
}
public void Chate() {
super.hate();
}
public void move() {
System.out.println("直线移动");
}
}
Test
package homework01;
public class Test {
public static void main(String[] args) {
Snake s = new Snake();
Centipede c = new Centipede();
s.setName("蛇");
c.setName("蜈蚣");
s.setHp(96);
c.setHp(100);
s.setAtk(2);
c.setAtk(1);
s.Shate();
c.Chate();
s.healing();
s.Shate();
s.move();
c.move();
}
}
作业二
2.请用面向对象的思想,设计自定义类描述演员和运动员的信息
设定
1)演员类:
属性包括:姓名,年龄,性别,毕业院校,代表作
方法包括:自我介绍
2)运动员类:
属性包括:姓名,年龄,性别,运动项目,历史最好成绩
方法包括:自我介始
要求
3)分析演员和运动员的公共成员,提取出父类—人类
4)利用继承机制,实现演员类和运动员类
5)编写测试类,分别测试人类,演员类和运动员类对象及相关方法
6)定义名为act的包存人类,演员类,运动员类和测试类
People
package homework02;
public class People {
private String name;
private int age;
private String sex;
public People() {
}
public People(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
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 getSex() {
return sex;
}
public void setSex(int sex) {
if(sex == 1){
this.sex = "男";
}else {
this.sex = "女";
}
}
public void introduce(){
System.out.println("名字" + name);
System.out.println("年龄" + age);
System.out.println("性别" + sex);
}
}
Actor
package homework02;
public class Actor extends People{
private String school;
private String maxter;
public Actor() {
}
public Actor(String school, String maxter) {
this.school = school;
this.maxter = maxter;
}
public Actor(String name, int age, String sex, String school, String maxter) {
super(name, age, sex);
this.school = school;
this.maxter = maxter;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
public String getMaxter() {
return maxter;
}
public void setMaxter(String maxter) {
this.maxter = maxter;
}
public void Acintro(){
System.out.println("我是一名演员");
super.introduce();
System.out.println("毕业于" + school);
System.out.println("代表作" + maxter);
}
}
Athletes
package homework02;
public class Athletes extends People{
private String sport;
private String history;
public Athletes() {
}
public Athletes(String sport, String history) {
this.sport = sport;
this.history = history;
}
public Athletes(String name, int age, String sex, String sport, String history) {
super(name, age, sex);
this.sport = sport;
this.history = history;
}
public String getSport() {
return sport;
}
public void setSport(String sport) {
this.sport = sport;
}
public String getHistory() {
return history;
}
public void setHistory(String history) {
this.history = history;
}
public void Atintro(){
System.out.println("我是一名运动员");
super.introduce();
System.out.println("运动项目" + sport);
System.out.println("历史最好成绩" + history);
}
}
Test
package homework02;
public class Test {
//
//2.请用面向对象的思想,设计自定义类描述演员和运动员的信息
// 设定
//1)演员类:
// 属性包括:姓名,年龄,性别,毕业院校,代表作
// 方法包括:自我介绍
//2)运动员类:
// 属性包括:姓名,年龄,性别,运动项目,历史最好成绩
// 方法包括:自我介始
// 要求
//3)分析演员和运动员的公共成员,提取出父类—人类
//4)利用继承机制,实现演员类和运动员类
//5)编写测试类,分别测试人类,演员类和运动员类对象及相关方法
//6)定义名为act的包存人类,演员类,运动员类和测试类
public static void main(String[] args) {
Actor ac = new Actor();
Athletes at = new Athletes();
ac.setName("彭于晏");
ac.setAge(20);
ac.setSex(1);
ac.setSchool("艺术大学");
ac.setMaxter("xxxx");
ac.Acintro();
System.out.println("----------------------------------");
at.setName("陈梦");
at.setAge(20);
at.setSex(0);
at.setSport("乒乓球");
at.setHistory("2024奥运会女子单打冠军");
at.Atintro();
}
}
作业三
3.编写企鹅类与狗类,企鹅类有属性姓名,健康值,亲密度,性别,
狗类有属性姓名,健康值,亲密度,品种。提取公共属性创建父类,
有共同的吃饭行为。使用构造函数初始化参数。
根据投递不同食物增加不同的亲密度,亲密度值(0-100)。食物自定义。
Pet
package homework03;
public class Pet {
private String name;
private int health = 100;
private int love = 100;
public Pet() {
}
public Pet(String name, int health, int love) {
this.name = name;
this.health = health;
this.love = love;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
public int getLove() {
return love;
}
public void setLove(int love) {
this.love = love;
}
public void eat(){
System.out.println("吃饭.....");
}
}
Dog
package homework03;
public class Dog extends Pet{
private String type;
public Dog(){}
public Dog(String name, int health, int love, String type) {
super(name, health, love);
this.type = type;
}
public String getType() {
return type;
}
public void setType(int type) {
if(type == 1){
this.type ="哈士奇";
}else{
this.type = "田园犬";
}
}
public void introduce(){
System.out.println(getName() + " " +getHealth() + " " +getLove() + " " + getType());
}
public void touwei(int food){
super.eat();
if (food == 2){
setLove(getLove()+2);
}else {
setLove(getLove()+1);
}
}
}
Penguin
package homework03;
public class Penguin extends Pet{
private String sex;
public Penguin(){}
public Penguin(String name, int health, int love, String sex) {
super(name, health, love);
this.sex = sex;
}
public String getSex() {
return sex;
}
public void setSex(int sex) {
if(sex == 1){
this.sex = "雄性";
}else{
this.sex = "磁性";
}
}
public void introduce(){
System.out.println(getName() + " " +getHealth() + " " +getLove() + " " + getSex());
}
public void touwei(int food){
super.eat();
if (food == 1){
setLove(getLove()+2);
}else {
setLove(getLove()+1);
}
}
}
Test
package homework03;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Penguin p = new Penguin();
Dog d = new Dog();
Scanner sc = new Scanner(System.in);
System.out.println("请选择你要查看的宠物 1、企鹅 2、狗狗");
if (sc.nextInt() == 1) {
System.out.println("请给你的宠物起个名字");
p.setName(sc.next());
System.out.println("请选择宠物性别 1、雄性 2、磁性");
p.setSex(sc.nextInt());
p.introduce();
System.out.println("请选择要投喂的食物 1、鱼 2、骨头");
p.touwei(sc.nextInt());
p.introduce();
}else{
System.out.println("请给你的宠物起个名字");
d.setName(sc.next());
System.out.println("请选择宠物品种 1、哈士奇 2、拉布拉多");
d.setType(sc.nextInt());
d.introduce();
System.out.println("请选择要投喂的食物 1、鱼 2、骨头");
d.touwei(sc.nextInt());
d.introduce();
}
}
}
作业四
4.程序分析题:
public class A{
public A(){
System.out.println("a");
}
}
public class B extends A{
public B(){
System.out.println("b");
}
}
B b = new B();
写出输出结果:
a
b