封装和继承
1. 封装
1.1 概念和思想
思想:我们之前直接使用等号给属性赋值,这样非常不合理,如果用户赋值了一些错误的值,我们没有机会去处理,相当于程序有比较高的耦合度,我们应该降低程序的耦合度,使用封装来解决。
封装 : 1.将类的信息尽可能的隐藏在类的内部 不让外部直接访问 使用private修饰属性即可 被private修饰的属性表示只能在本类中访问 其他类不能访问
2.而是提供一对公开的getter和setter方法用于访问属性
package com.qfedu.test1;/*** 企鹅类** 健康值* 名字* 性别** 封装 :* 1.将类的信息尽可能的隐藏在类的内部 不让外部直接访问* 使用private修饰属性即可* 被private修饰的属性表示只能在本类中访问 其他类不能访问* 2.而是提供一对公开的getter和setter方法用于访问属性* getter方法用于获取属性值* setter方法用于设置属性值* @author WHD**/public class Penguin {private int health;private String sex;private String name;public int getHealth(){return health;}public void setHealth(int health) {if(health >=0 && health <= 100) {this.health = health;}else {System.out.println("健康值赋值不合理,将使用默认值60");this.health = 60;}}public void setName(String name) {this.name = name;}public String getName() {return name;}public void setSex(String sex) {if(sex.equals("雌") || sex.equals("雄")) {this.sex = sex;}else {System.out.println("性别不合适,使用默认性别雌性");this.sex = "雌";}}public String getSex() {return sex;}}
2. 访问权限修饰符
2.1 类的访问权限修饰符
1.public 本项目中任何位置都可以访问 2.默认不写 本包中可以访问
2.2 类成员的访问权限修饰符
1.private 表示私有的本类中可以访问 2.默认不写的 本包中可以访问 3.protected 受保护的 本类中 本包中 子类中 4.public 本项目中任何位置都可以访问
package com.qfedu.test2;/*** 类的访问修饰符:* 1.public 本项目中任何位置都可以访问* 2.默认不写 本包中可以访问** 类成员(属性和方法)的访问修饰符:* 1.private 表示私有的本类中可以访问* 2.默认不写的 本包中可以访问* 3.protected 受保护的 本类中 本包中 子类中* 4.public 本项目中任何位置都可以访问* @author WHD**/public class Note {private String field1;String field2;protected String field3;public String field4;private void m1() {}void m2() {}protected void m3() {}public void m4() {}public static void main(String[] args) {A a = new A(); // 同类中Note note = new Note();System.out.println(note.field1); // 红色方框 私有System.out.println(note.field2); // 蓝色三角 包级别System.out.println(note.field3); // 黄色菱形 受保护的 本类 本包 子类System.out.println(note.field4); // 绿色原点 最大范围 publicnote.m1();note.m2();note.m3();note.m4();}}class A{}
package com.qfedu.test2;public class Test {public static void main(String[] args) {A a = new A(); // 同包中 可以访问// 访问属性Note note = new Note();System.out.println(note.field2);System.out.println(note.field3);System.out.println(note.field4);note.m2();note.m3();note.m4();}}
package com.qfedu.test3;import com.qfedu.test2.Note;/*** 属性访问和类访问* @author WHD**/public class Test {public static void main(String[] args) {// A a = new A(); 因为A是包级别的访问权限 所以不同包不能访问Note note = new Note();System.out.println(note.field4);note.m4();}}
3. static关键字
3.1 static适用场景
static可以用来修饰
成员变量
静态变量,可以直接通过类名访问成员方法
静态方法,可以直接通过类名访问代码块
静态代码块,当Java虚拟机加载类时,就会执行该代码块
3.2 static修饰变量
被static修饰的变量在内存中只有一个拷贝,可以用于数据共享,实现多个实例之间的数据传递
类内部,可在任何方法内直接访问静态变量
其他类中,可以直接通过类名访问
package com.qfedu.test4;/*** 接水* @author WHD**/public class Person {static int capacity = 10000; // 容量 1000毫升水String name; // 名字public void getWater() {if(capacity > 0) {capacity -= 200;System.out.println(name + "接水200毫升,还剩下" + capacity + "毫升");}else {System.out.println("没水了,请换水");}}}
package com.qfedu.test4;public class TestPerson {public static void main(String[] args) {Person zhaosi = new Person();zhaosi.name = "赵四";zhaosi.getWater();Person guangkun = new Person();guangkun.name = "广坤";guangkun.getWater();Person xiaobao = new Person();xiaobao.name = "小宝";xiaobao.getWater();// 问题2:我们发现不能按照设想将水容量这个数据共享// 因为capacity是实例变量 每new一个对象在内存中就 存在一份// 所以我们new三个对象 内存中有三个capacity 值都为1000}}
package com.qfedu.test5;/*** 选民类* 选民名称* 总票数* @author WHD**/public class Voter {static int ticketCount = 100;String name;public boolean voteFor() {if(ticketCount > 0) {ticketCount --;System.out.println(name + "投了一票,还剩余" + ticketCount);return true;}else {System.out.println("投票完毕请等待 下一届");return false;}}public static void main(String[] args) {Voter v1 = new Voter();v1.name = "赵四";v1.voteFor();Voter v2 = new Voter();v2.name = "大拿";v2.voteFor();Voter v3 = new Voter();v3.name = "小宝";v3.voteFor();for (int i = 1; i < 120; i++) {Voter v = new Voter();v.name = i + "号选民";if(!v.voteFor()) {break;}}}}
3.3 static修饰方法
静态方法:可直接通过类名访问
静态方法中不能使用this和super
不能直接访问所属类的实例变量和实例方法
可直接访问类的静态变量和静态方法
实例方法:通过实例访问
可直接访问所属类的静态变量、静态方法、实例变量和实例方法
静态方法必须被实现
package com.qfedu.test5;/*** 1.静态与静态直接调用* 2.静态访问非静态 必须先new对象* 3.非静态的访问静态的 直接调用* @author WHD**/public class TestStaticMethod {public void m3() {m1();}public void m1() {m2(); // 直接调用 因为实例方法m1可以调用的时候 类一定被加载过了// 静态方法已经初始化过了System.out.println("普通方法m1");}public static void m2() {// m1(); 不能直接调用m1 必须先new对象// 因为m2方法初始化的时候 m1方法不一定存在(必须依赖对象而存在)System.out.println("静态方法m2");}public static void main(String[] args) {TestStaticMethod.m2();TestStaticMethod tsm = new TestStaticMethod();tsm.m1();}}
package com.qfedu.test5;public class Test1 {public static void main(String[] args) {TestStaticMethod tsm = new TestStaticMethod();tsm.m1();TestStaticMethod.m2();tsm.m3();}}
3.4 static修饰代码块
随着类被加载执行 多个静态代码块按照书写顺序执行 每个只执行一次 因为类只加载一次
静态代码块用于实现一些前置的操作 比如数据初始化 等
普通代码块 每new一次对象 执行一次
package com.qfedu.test5;/*** 静态代码块* 随着类被加载执行 多个静态代码块按照书写顺序执行 每个只执行一次 因为类只加载一次** 静态代码块用于实现一些前置的操作 比如数据初始化 等* @author WHD**/public class TestStaticCode {static int num = 10;static {System.out.println("静态代码块1");}static {System.out.println("静态代码块2");}{System.out.println("实例代码块1");}{System.out.println("实例代码块2");}public static void main(String[] args) {System.out.println(num);TestStaticCode tsc1 = new TestStaticCode();TestStaticCode tsc2 = new TestStaticCode();TestStaticCode tsc3 = new TestStaticCode();}}
3.5 访问规则
1.静态与静态直接调用 2.静态访问非静态 必须先new对象 3.非静态的访问静态的 直接调用
4. 类加载的过程
4.1 名词解释
方法区:是JDK提供的一个规范,符合这个规范即可称之为方法区 元空间:方法区的实现,JDK1.8叫元空间,用来加载类信息文件,初始化静态相关信息等 永久代:JDK1.7 之前叫永久代,方法区的实现
4.2 加载过程
1.当我们第一次访问一个类时,JVM先在方法区查看是否有加载当前类信息文件 如果有,在堆中开辟空间,将栈中的引用指向堆中的空间 如果没有,先加载类信息文件,然后在堆中开辟空间,将栈中的引用指向堆中的空间

