目录
1. 封装
封装:面向对象三大特征之一
属性私有:将所有的属性使用private访问权限修饰符修饰 表示此属性只能在本类中访问 其他类无法访问
方法公开:针对每一个属性编写一堆对方法
getter方法 用于获取属性值
setter方法 用于设置属性值
高内聚:本类中的信息应该与本类直接产生关联关系 不能间接关联 或者没有关联
低耦合:耦合度是指程序各个类 各个组件 模块 之间的紧密联系程度 降低耦合度有利于程序的扩展 以及 维护
public class Penguin {
private String name;
private char sex;
private int health;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setSex(char sex){
if(sex == '雌' || sex == '雄'){
this.sex = sex;
}else{
System.out.println("性别赋值不合法,使用默认性别:雌");
this.sex = '雌';
}
}
public char getSex(){
return sex;
}
public void setHealth(int health){
if(health >= 0 && health <= 100){
this.health = health;
}else{
System.out.println("健康值赋值不合法,使用默认值60");
this.health = 60;
}
}
public int getHealth(){
return health;
}
}
2. 访问权限修饰符
2.1 类的访问权限修饰符
默认不写:表示在本包中可以访问
public:任何位置都可以访问
2.2 类成员的访问权限修饰符
private:本类
默认不写:本类 本包
protect:本类 本包 以及 任何位置的子类中
public:任何位置
3. 继承
子类继承父类 子类与父类是 is--a 的关系,即:子类是父类
例如:笔记本电脑是电脑 台式电脑是电脑
继承是Java中实现代码重用的重要手段之一
Java中只支持单继承,即一个类只能有一个直接父类
父类:父类中书写各个子类共有的信息 即方法和属性
子类:子类中书写独有的信息和方法
继承关键字:extends
public class Pet {
private String name;
private int health;
private int 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 print(){
System.out.println("宠物的名字是:" + name);
System.out.println("宠物的健康值是:" + health);
System.out.println("宠物的亲密值是:" + love);
}
}
public class Dog extends Pet{
private String strain;
public String getStrain() {
return strain;
}
public void setStrain(String strain) {
this.strain = strain;
}
public Dog(){}
}
public class Penguin extends Pet{
private String sex;
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Penguin(){}
}
public class TestPet {
public static void main(String[] args) {
Dog dog = new Dog();
dog.setName("大黄");
dog.setStrain("哈士奇");
dog.setHealth(100);
dog.setLove(100);
dog.print();
System.out.println(dog.getStrain());
System.out.println("============================================");
Penguin penguin = new Penguin();
penguin.setName("大白");
penguin.setHealth(100);
penguin.setSex("雌");
penguin.setLove(100);
penguin.print();
System.out.println(penguin.getSex());
}
}
4. super 关键字
4.1 super 关键字访问属性
super 关键字可以直接访问继承自父类的属性 前提要求 访问权限允许
public class Pet {
protected String name;
protected int health;
protected int love;
public void print(){
System.out.println("宠物的名字是:" + name);
System.out.println("宠物的健康值是:" + health);
System.out.println("宠物的亲密值是:" + love);
}
}
public class Penguin extends Pet {
String sex;
public Penguin(){}
public Penguin(String name,int health,int love,String sex){
this.sex = sex;
super.name = name;
super.health = health;
super.love = love;
}
}
4.2 super 关键字访问方法
super 关键字可以直接访问继承自父类的方法前提要求 访问权限允许
public class Pet {
protected String name;
protected int health;
protected int love;
public void print(){
System.out.println("宠物的名字是:" + name);
System.out.println("宠物的健康值是:" + health);
System.out.println("宠物的亲密值是:" + love);
}
}
public class Dog extends Pet {
String strain;
public void printDog(){
print(); //
System.out.println("狗狗的品种是:" + strain);
}
}
public class Penguin extends Pet {
String sex;
public void printPenguin(){
super.print();
System.out.println("企鹅的性别是:" + sex);
}
}
4.3 super关键字访问构造方法
访问父类构造方法 必须在子类构造的第一句(所以在一个构造方法中 不能同时使用 this 和 super 访问本类以及父类的构造)
子类中的每个构造方法,默认访问父类的无参构造方法
除非子类构造方法显示访问父类的有参构造方法
总结:子类构造方法必须访问父类的无参或有参构造方法中的一个
public class Pet {
protected String name;
protected int health;
protected int love;
public Pet(){ //无参构造
}
public Pet(String name,int health,int love){ //有参构造
this.name = name;
this.health = health;
this.love = love;
}
}
public class Dog extends Pet {
String strain;
public Dog(){
}
public Dog(String name,int health,int love,String strain){
super(name,health,love);
this.strain = strain;
}
}
public class Cat extends Pet {
String furColor;
public Cat(){
}
public Cat(String name,int health,int love,String furColor){
super(name, health, love);
this.furColor = furColor;
}
}
5. 子类继承
能够继承public 和 protected 修饰的属性和方法,不管子类和父类是否在同一个包里
能够继承默认权限修饰的属性和方法,但子类和父类必须在同一个包里
不能继承private 修饰的属性和方法
不能继承父类的构造方法
6. super 关键字 和 this 关键字内存图
在子类中,可以使用super关键字访问的内容,同时可以使用this访问
new 子类对象 会调用子类构造方法 在调用子类构造方法之前 必须先调用父类的构造方法(默认访问无参构造,除非显示访问有参构造)
1.调用父类构造方法的作用
用于将父类的属性初始化
无参构造初始化默认值
有参构造则是传参
2.关于调用父类构造方法
注意:调用父类构造方法不会创建父类对象 只是为了初始化父类属性值
3.super 和 this 的关系
super 表示父类的信息 是包含在this之内的 每一个子类对象中都会包含父类的属性信息
4.不能继承 却在内存中还有属性值
第一:按照这样记忆
第二:Java官方说明的
6. static 关键字
6.1 修饰属性
static 修饰的属性称之为静态变量(类变量)被static 修饰的属性在内存中只存在一份 不属于任何对象 而是属于整个类 可以被此类的所有对象共享
如果有每个对象都共同的数据 我们可以使用static 修饰 以节省内存空间
因为static修饰的内容,通常用于被多个对象共享数据的数据,所以这样的数据通常要求不能随意改变
关于静态变量访问:
因为静态变量不属于任何对象 故不推荐使用对象名加点访问 推荐使用类名加点访问
本类中 直接访问
其他类 通过类名加点访问 前提:访问权限必须允许
public class Person {
static int capacity = 100; // 单位 L
String name;
public void getWater(){
if(capacity > 0){
capacity--;
System.out.println(name + "接水1升,还剩余" + capacity + "升");
}else{
System.out.println("没水了,请注水");
}
}
public static void main(String[] args) {
Person zs = new Person();
zs.capacity = 500 ;
zs.name = "赵四";
zs.getWater();
System.out.println(zs.capacity);
Person ln = new Person();
ln.name = "刘能";
ln.getWater();
System.out.println(ln.capacity);
Person gk = new Person();
gk.name = "广坤";
gk.getWater();
System.out.println(gk.capacity);
}
}
public class Student {
String name;
int age;
static String country ="中华人民共和国";
public static void main(String[] args) {
Student stu1 = new Student();
stu1.name = "赵四1";
stu1.age = 20;
System.out.println(stu1.country);
stu1.country = "中国";
Student stu2 = new Student();
stu2.name = "赵四2";
stu2.age = 20;
System.out.println(stu2.country);
Student stu3 = new Student();
stu3.name = "赵四3";
stu3.age = 20;
System.out.println(stu3.country);
}
}
6.2 修饰方法
静态与实例之间的访问规则:
静态方法中不能使用this 和 super
静态访问静态 直接访问
实例访问实例 直接访问
同级别相互直接访问
实例访问静态 直接访问
静态访问实例 必须先new 对象 例如main方法访问实例级别的信息 属性 和方法
public class TestStaticMethod {
public static void m1(){
System.out.println("静态方法m1");
}
public static void m2(){
System.out.println("静态方法m2");
m1();
}
public void m3(){
m1();
m2();
System.out.println("实例方法m3");
}
public void m4(){
System.out.println("实例方法m4");
m3();
}
public static void main(String[] args) {
m1();
m2();
TestStaticMethod testStaticMethod = new TestStaticMethod();
testStaticMethod.m3();
testStaticMethod.m4();
}
}
public class Test {
public static void main(String[] args) {
TestStaticMethod.m1();
TestStaticMethod.m2();
TestStaticMethod tsc = new TestStaticMethod();
tsc.m3();
tsc.m4();
}
}
6.3 修饰代码块
static 修饰代码块: 称之为静态代码块 随着JVM 加载类而执行 因为类只加载一次 所以静态代码块也只执行一次
多个静态代码块按照书写顺序执行
类什么时候会被加载?
1.创建对象
2.访问此类中的任何静态信息
什么时候使用静态代码块:静态代码块通常来执行一些前置操作
比如 数据库连接、数据初始化
普通代码块:随着对象的创建而执行 每创建一个对象就执行一次
public class TestStaticCode {
static int num;
static{
System.out.println("静态代码块1");
}
static{
System.out.println("静态代码块2");
}
{
System.out.println("普通/实例 代码块1");
}
{
System.out.println("普通/实例 代码块2");
}
public TestStaticCode() {
System.out.println("无参构造方法");
}
public static void main(String[] args) {
TestStaticCode tsc1 = new TestStaticCode();
// TestStaticCode tsc2 = new TestStaticCode();
// System.out.println(num);
}
}
7. 静态关键字总结
名词解释:
方法区:方法区是SUN公司指定的规范,是JVM内存的一块区域
永久代:是JDK 7 对方法区具体的名称
元数据 / 原空间:是JDK 8 方法区具体的名称
对象创建的过程:
1.先将此对象对应的class文件加载到方法区
如果此类已经被加载 则直接执行第二部创建对象
如果此类没有被加载 则先加载
此时静态的属性将被初始化 有具体的值或者默认值
2.在堆中开辟空间 此时实例级别的属性将会初始化
3.将堆中的地址值赋值给栈中的引用 完成对象的创建
关于静态的和实例(动态)级别的
静态的数据会随着类的加载而存在 而且不会轻易回收 回收效率更低 但是只存在一份 也节省内存空间
实例级别的数据会随着对象的创建而存在 可以轻易回收 回收效率更高 但是每创建一个对象就单独存在一份
//静态类练习
public class Voter {
String name;
static int ticketCount = 100;
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 zs = new Voter();
zs.name = "赵四";
zs.voteFor();
Voter gk = new Voter();
gk.name = "广坤";
gk.voteFor();
Voter dn = new Voter();
dn.name = "大拿";
dn.voteFor();
for(int i = 1;i < 120;i++){
Voter v1 = new Voter();
v1.name = i + "号选民";
if(!v1.voteFor()){ // == false
break;
}
}
}
}
8. 方法重写
方法重写 overrides
1.存在于父子类之间
2.方法名相同
3.参数列表相同
4.返回值相同 或者是其子类
5.访问权限不能严于父类 必须大于等于父类 不能窄化父类方法的访问权限
6.不能抛出或者声明比父类更多的异常
7.静态方法可以被继承 但是不能被重写
注解 @Override 此注解用于书写在方法上 表示此方法属于重写父类的方法 次注解可以帮助我们正确重写父类的方法
同时提高代码的阅读性
public class Pet {
private String name;
private int health;
private int 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 print(){
System.out.println("宠物的名字是:" + name);
System.out.println("宠物的健康值是:" + health);
System.out.println("宠物的亲密值是:" + love);
}
}
public class Dog extends Pet {
private String strain;
public String getStrain() {
return strain;
}
public void setStrain(String strain) {
this.strain = strain;
}
/**
* 方法重写 Overrides
* 1.存在父子类之间
* 2.方法名相同
* 3.参数列表相同
* 4.返回值相同 或者是其子类
* 5.访问权限不能严于父类 必须大于等于父类 不能窄化父类方法的访问权限
*
* 6.不能抛出或者声明比父类更多的异常
* 7.静态方法可以被继承 但是不能被重写
*
* 注解 @Override 此注解用于书写在方法上 表示此方法属于重写父类的方法 次注解可以帮助我们正确重写父类的方法
* 同时提高代码的阅读性
*/
@Override
public void print(){
super.print();
System.out.println("狗狗的品种是:" + strain);
}
}
public class Penguin extends Pet {
private String sex; // alt + insert
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void printPenguin(){
super.print();
System.out.println("企鹅的性别是:" + sex);
}
}