封装与继承
面向对象的三大特性:封装、继承、多态(如果有第四个 就是抽象)
1.掌握什么是封装
封装的作用:
如果没有封装,那么一个类中的属性,可能会出现不合理赋值
便于使用者正确使用系统,防止错误修改属性
有助于系统之间的松耦合,提高系统独立性
提高软件的可重用性
降低了构建大型系统的风险
封装的定义:将类的信息封装在类的内部,不允许外部程序直接访问,而是通过类提供的公开的接口进行访问赋值等
原则:尽可能多的隐藏信息。都通过公开的接口来访问
2.掌握如何使用封装
package cn.FangFaJiFangFaChongZai.www;
public class PetPackage {
private String name = "二哈";
private int health = 100;
private int love = 100;
private String strain = "哈士奇";
// 为属性health加一对setter/getter
public void setHealth(int health){
if((health < 0) || (health > 100)) {
// 如果健康值小于0或者大于100,则强制赋值为60,并提示用户,然后结束方法
this.health = 60;
System.out.println("健康值赋值不合适!");
return;
}
// 如果健康值合法,则可以直接赋值
this.health = health;
}
public int getHealth(){
return this.health;
}
// 为属性name加一对setter/getter
public void setName(String name){
this.name = name;
return;
}
public String getName(){
return this.name;
}
// 为属性love加一对setter/getter
public void setLove(int love) {
if(love < 0) {
this.love = 60;
System.out.println("亲密度不能为负数");
return;
}
this.love = love;
}
public int getLove() {
return this.love;
}
// 为属性strain加一对setter/getter
public void setStrain(String strain) {
this.strain = strain;
return;
}
public String getStrain() {
return this.strain;
}
public void print() {
System.out.println("名字:"+this.name+" 健康值:"+this.health+" 亲密度:"+this.love+" 品种:"+this.strain);
}
}
package cn.FangFaJiFangFaChongZai.www;
public class TestPetPackage {
public static void main(String[] args) {
PetPackage dog = new PetPackage();
dog.setHealth(-111);
//只想获取健康值: System.out.println("健康值为:"+dog.getHealth());
dog.setName("二哈");
dog.setLove(12);
dog.setStrain("哈士奇");
dog.print();
}
}
Alt+Shift+S 快捷键创建setter/getter
3.包的作用和使用
为什么需要包:
1.因为在各个系统中,通过一个目录下不允许出现同名的文件
2.当我们文件(java代码等)越来越多的时候,全都放在一起会显得杂乱,不易管理,有一定规则 的包可以解决此问题
3.有助于实施访问权限控制
试用包:
包名的命名规则:
1.所有的字母都小写(大多数场景下)
2.采用反域名命名法(公司域名倒序)例如:com.kgc.xxx
3.各级包应该有一定的规范:(根据不同公司会有出入)
cn 一级包
kgc 二级包 公司的名称
项目的名称 三级包
模块名或者层级名 四级包
导入包(Ctrl+Shift+O):快速导包
// 导包:如果你要使用的类[不再同一个包下] 你就需要将它的地址导入过来
// 导包的语句必须是在类声明的上方,包声明的下方
// 语法:import 类的全类名/全路径/全限定名;(它也支持通配符)
// import java.util.*;
import java.util.Scanner;
1.包(package)声明必须在第一句,然后是import,然后是类(class);
2.包(package)只能有一句,也可以没有,但是import可以有多句;
3.java.lang.xxx包下的类,不需要你手动声明,JVM会自动进行加载
特殊情况:如果想使用多个同名的不在同一个包里的类,写这个类的完整限定名
com.kgc.oop.Dog dog = new com.kgc.oop.Dog();
com.kgc.oop.pet.Dog dog = new com.kgc.oop.pet.Dog();
4.访问修饰符
private:最严格的访问级别,只能在本类使用
无访问修饰符的:同包之间可以随意访问
protected:
public:在整个项目里都可以使用
访问修饰符:可以用来修饰类,修饰方法,修饰属性
作用:为了隐藏某些细节,或者公开某些内容。控制访问权限
5.static关键字
静态方法:可直接通过类名访问
静态方法中不能使用this和super
不能直接访问所属类的实例变量和实例方法
可直接访问类的静态变量和静态方法
实例方法:通过实例访问
可直接访问所属类的静态变量、静态方法、实例变量和实例方法
静态方法必须被实现
在方法里不可以定义static变量
static可以修饰变量:静态变量/类变量
static也可以修饰方法:静态方法/类方法
static也可以修饰代码块:静态代码块(只会执行一次)
public class Dog{
// 成员代码块/构造代码块/非静态代码块:会随着对象的创建而执行里面的代码块片段(创建一次对象就执行一次),优先于构造方法执行
{
}
// 非静态代码块:会随着类的加载而执行里面的代码片段(只会执行一次)
static{
}
}
static修饰的类变量和普通的成员变量的区别:
1.生命周期不同
类变量随着类加载而加载
实例变量随着对象产生而创建
2.”作用域“不同
类变量被该类的所有对象共享,只要有一个对象更改,所有对象获取的结果都会更改
实例变量仅仅被自身对象所使用,不同对象之间的实例变量相互独立存在
3.调用上不同
实例信息必须先创建对象才能使用
类信息,可以直接用类名的形式调用,也可以用对象来调用
注意事项:
1.如果多个对象之间有共享的数据,且这个数据不会发生变动,最好定义为静态常量,可以有效提升效率。
static final 修饰。。。
2.在类信息中,如果使用实例信息,需要注意先创建对象才能使用,而反之则无所谓(自己思考谁先出生谁后出生)
6.继承的作用和使用
继承的作用
便于复制代码
将子类中共有的代码,提取出来存储到父类中,到时候用子类继承父类就可以重复使用父类的代码
理解继承
父类不是所有的内容都能被子类继承
1.父类私有的被private修饰的
2.父类的构造方法
3.如果父类不在同一个包里,那么父类被默认修饰符修饰的内容不能被继承
super关键字来访问父类的成员
super只能出现在子类的方法和构造方法
super调用构造方法时,只能是第一句
super不能访问父类的private成员
继承条件下的构造方法
子类构造方法没有通过super显式调用父类的有参构造方法,也没有通过this显式调用自身其他构造方法
系统默认调用父类的无参构造方法
子类构造方法通过super显式调用父类的有参构造方法
执行父类相应构造方法,而不执行父类无参构造方法
子类构造方法通过this显式调用自身的其他构造方法,是相应构造方法中应用以上两条规则