3、面向对象之封装与继承(找工作版)
文章目录
- 一、Java面向对象
- 1、类和对象
- 2、实例化对象
- 3、构造方法
- 4、this关键字
- 5、总结
- 二、Java封装
- 1、封装的概念和特点
- 2、使用包进行类管理
- 3、static关键字
- 4、代码块
- 5、总结
- 三、综合案例:学生信息管理
- 四、Java继承
一、Java面向对象
1、类和对象
-
类是模子,确定对象将会拥有的特征(属性)和行为(方法)
类的特点:类是对象的类型;具有相同属性和方法的一组对象的集合。 -
属性:对象具有的各种静态特征,“有什么”
方法:对象具有的各种动态行为,“对象能做什么”
类和对象的关系:
- 类是抽象的概念,仅仅是模板
- 对象是一个你能够看得到、摸得着的具体实体
- 类是对象的类型
- 对象是特定类型的数据
- 具体开发过程中,先定义类再实例化对象
- Cat.java
package com.imooc.animal;public class Cat {//成员属性:昵称、年龄、体重、品种String name; //String 类型默认值为nullint month; //int 类型默认值为0double weight; //double 类型默认值为0.0String species;//成员方法:跑动、吃东西public void run() {System.out.println("小猫快跑");}public void run(String name) {System.out.println(name+"快跑");}public void eat() {System.out.println("小猫吃鱼");}
}
- CatTest.java
package com.imooc.animal;public class Cat {//成员属性:昵称、年龄、体重、品种String name; //String 类型默认值为nullint month; //int 类型默认值为0double weight; //double 类型默认值为0.0String species;//成员方法:跑动、吃东西public void run() {System.out.println("小猫快跑");}public void run(String name) {System.out.println(name+"快跑");}public void eat() {System.out.println("小猫吃鱼");}
}
输出:
小猫吃鱼
小猫快跑
昵称:花花
年龄:2
体重:1000.0
品种:英国短毛猫
花花快跑
2、实例化对象
Java程序运行过程会涉及到的两大重要内存区域一堆和栈
- 栈:每个方法(Method)在执行时,都会创建一个栈,用于存储局部变量表、操作数、动态链接、方法出口信息等。
需要注意,栈中所存储,多用于保存局部信息的值,譬如:方法体中的基本数据类型定义的变量、对象的引用(也称为对象实例)等。当局部作用范围结束时,栈内信息立即自动释放。
当存储内容是由基本数据类型(byteshrtint、long、float、doublechar boolean)声明的局部变量时,在栈中存储的是它们对应的具体数值。
当存储的是局部的对象的引用(定义在方法体中的引用类型的变量),存储的是具体对象在堆中的地址。当然,如果对象的引用没有指向具体的空间,则是null。- 堆:用来存放动态产生的数据,比如new出来的对象。当对象使用结束,并确定已无实例引用指向堆空间时,JVM才会依据相关垃圾回收机制进行资源回收,完成堆内资源释放,也就是说,并不是方法结束,方法内涉及到的堆空间就会立即释放,这也是与栈管理不同的地方。
此时,需要注意,创建出来的对象只包含属于各自的成员变量,并不包括成员方法。因为同一个类拥有各自的成员变量,存储在堆中的不同位置,但是同一个类不同实例的之间共享该类的方法,并不是每创建一个对象就把成员方法复制一次。
package com.imooc.animal;
// 单一职责原则
public class CatTest {public static void main(String[] args) {// 实例化对象Cat one=new Cat();Cat two=one;// 测试one.name="花花";one.month=2;one.weight=1000;one.species="英国短毛猫";two.name="饭饭";two.month=1;two.weight=800;two.species="中华田园猫";System.out.println("昵称:"+one.name);System.out.println("年龄:"+one.month);System.out.println("体重:"+one.weight);System.out.println("品种:"+one.species);System.out.println("——————————————————");System.out.println("昵称:"+two.name);System.out.println("年龄:"+two.month);System.out.println("体重:"+two.weight);System.out.println("品种:"+two.species);}
}
输出:
昵称:饭饭
年龄:1
体重:800.0
品种:中华田园猫
——————————————————
昵称:饭饭
年龄:1
体重:800.0
品种:中华田园猫
3、构造方法
4、this关键字
总结:
- 1、可以在构造方法中,通过this调用本类中的另一个构造方法,但是,调用动作必须置于方法中的第一行。
- 2、可以通过this调用本类中带参或者无参构造方法,调用带参构造方法时,需要按顺序传入设定的参数。
- 3、在一个构造方法内只能调用一个构造方法。
- 4、不能在类中普通成员方法内通过this调用构造方法
- Cat.java
package com.imooc.animal;public class Cat {//成员属性:昵称、年龄、体重、品种String name; //String 类型默认值为nullint month; //int 类型默认值为0double weight; //double 类型默认值为0.0String species;public Cat() {System.out.println("我是无参构造方法");}public Cat(String name) {System.out.println("我是带参构造方法");}public Cat(String name,int month,double weight,String species) {this("aaa");//同一个类的构造方法之间用this()调用this.name=name;this.month=month;this.weight=weight;this.species=species;}//成员方法:跑动、吃东西public void run() {this.eat();System.out.println("小猫快跑");}public void run(String name) {System.out.println(name+"快跑");}public void eat() {System.out.println("小猫吃鱼");}
}
- CatTest.java
package com.imooc.animal;
// 单一职责原则
public class CatTest {public static void main(String[] args) {// 实例化对象Cat one=new Cat("花花",2,1000,"英国短毛猫");System.out.println("昵称:"+one.name);System.out.println("年龄:"+one.month);System.out.println("体重:"+one.weight);System.out.println("品种:"+one.species);one.run();}
}
- 输出
我是带参构造方法
昵称:花花
年龄:2
体重:1000.0
品种:英国短毛猫
小猫吃鱼
小猫快跑
5、总结
构造方法与类中成员方法的区别是什么?
- 1、作用:
构造方法:用于生成并初始化对象,针对不同的初始化状态,设置不同参数的构造方法。
成员方法:根据类型所需任意功能,进行方法设置。- 2、格式:
构造方法:访问修饰符 类名(参数列表){…}
成员方法:访问修饰符 返回值类型 方法名(参数列表){…}- 3、特点:
构造方法:
(1)方法名必须与类名相同,包括大小写。
(2)没有返回值,也不能用void修饰。
(3)如果在定义类时没有定义构造方法,则编译系统会自动插入一个无参数且无方法体的构造方法以完成对象实例化。如果类中显式地定义了一个或多个构造方法,则编译器不再提供默认构造方法。
(4)类中可以包含多个构造方法,多个构造方法之间可以通过this进行调用,但仅可在第一行执行调用。
(5)只能与new一起进行调用,不能通过对象名、类名等其他形式调用。
(6)在非构造方法中,只能结合对象实例化操作被调用,不能通过方法名被访问。
成员方法:
(1)方法名符合Java命名规范即可。
(2)需要设置返回值,如果方法体中无返回值,需要用void设置。
(3)类中可以包含多个同名成员方法,类内方法间可以在任意位置进行调用。类外,当访问权限允许时,可以通过对象名.方法名()形式调用。
(4)语法层面来说,可以存在方法名与类名相同的成员方法,但并不推荐。
二、Java封装
1、封装的概念和特点
概念:
- 将类的某些信息隐藏在类内部,不允许外部程序直接访问
- 通过该类提供的方法来实现对隐藏信息的操作和访问
- 隐藏对象的信息
- 留出访问的接口
特点:
- 只能通过规定的方法访问数据
- 隐藏类的实例细节,方便修改和实现
- 只有getXXX方法的属性是只读属性,只有setXXX方法的属性是只写属性。
package com.imooc.animal;public class Cat {//成员属性:昵称、年龄、体重、品种// 修改属性的可见性----private 限定只能在当前类内访问private String name; //String 类型默认值为nullprivate int month; //int 类型默认值为0private double weight; //double 类型默认值为0.0private String species;public Cat() {}public Cat(int month) {this.setMonth(month);}// 创建get/set方法// 在get/set方法当中添加对属性的限定public void setName(String name) {this.name = name;}public String getName() {return "我是一只名叫:"+this.name+"的宠物猫";}public int getMonth() {return month;}public void setMonth(int month) {if(month<0)System.out.println("输入信息错误,宠物猫的年龄必须是大于0");elsethis.month = month;}public double getWeight() {return weight;}public void setWeight(double weight) {this.weight = weight;}public String getSpecies() {return species;}public void setSpecies(String species) {this.species = species;}
}
package com.imooc.animal;
// 单一职责原则
public class CatTest {public static void main(String[] args) {// 实例化对象Cat one=new Cat(-3);// one.setName("饭饭");
// one.setMonth(-3);
// one.setWeight(1200);
// one.setSpecies("中华田园猫"); // System.out.println("昵称:"+one.getName());if (one.getMonth() == 0)return;System.out.println("年龄:"+one.getMonth());
// System.out.println("体重:"+one.getWeight());
// System.out.println("品种:"+one.getSpecies());}
}
输出:
输入信息错误,宠物猫的年龄必须是大于0
2、使用包进行类管理
- 建议采用“import 包名.类名;”的方式加载,以提高效率。
- 加载类的顺序与import导入语句的位置无关。
- "import 包名.*;"只能访问指定包名下的类,无法访问子包下的类。
3、static关键字
4、代码块
- 普通代码块:顺序执行,先出现,先执行。
- 构造代码块:创建对象时调用优先于构造方法执行。
- 静态代码块:类加载时调用,优先于构造代码块执行。
- 无论实例产生多少对象,静态代码块只执行一次。仅希望执行一次的代码可以放在静态代码块中。
- 构造代码块随实例化过程调用,普通代码块随方法调用执行。
package com.imooc.animal;public class Cat {//成员属性:昵称、年龄、体重、品种// 修改属性的可见性----private 限定只能在当前类内访问private String name; //String 类型默认值为nullprivate int month; //int 类型默认值为0private double weight; //double 类型默认值为0.0private String species;// static 静态成员、类成员// static+属性--》静态属性、类属性public static int price;//售价public Cat() {System.out.println("我是宠物猫~");}public Cat(int month) {this.setMonth(month);}{name="妞妞";price=130;System.out.println("我是构造代码块1");}static{price=290;Cat temp=new Cat();temp.name="小胖";System.out.println("我是静态代码块");}// 创建get/set方法// 在get/set方法当中添加对属性的限定public void setName(String name) {this.name = name;}public String getName() {return "我是一只名叫:"+this.name+"的宠物猫";}public int getMonth() {return month;}public void setMonth(int month) {if(month<0)System.out.println("输入信息错误,宠物猫的年龄必须是大于0");elsethis.month = month;}public double getWeight() {return weight;}public void setWeight(double weight) {this.weight = weight;}public String getSpecies() {return species;}public void setSpecies(String species) {this.species = species;}//在成员方法中,是可以直接访问类中静态成员public void run() {eat();this.name="妞妞";this.price=20;System.out.println("售价是"+Cat.price+"的"+this.name+"快跑");}public void run(String name) {{int temp=12;System.out.println("我是普通代码块1,temp="+temp);}System.out.println(name+"快跑");{int temp=13; System.out.println("我是普通代码块2,temp="+temp);}}//static+方法--》类方法,静态方法public static void eat() {//静态方法中不能直接访问同一个类的非静态成员,只能直接调用同一个类中静态成员//只能通过对象实例化后,对象.成员方法的方式访问非静态成员Cat temp = new Cat();temp.run();
// this.name="小胖";//静态方法中不能使用thistemp.name="小胖";price=1500;System.out.println("小猫吃鱼");}
}
package com.imooc.test;//定义包
//import com.imooc.animal.*; //加载animal下所有类
import com.imooc.animal.Cat; //加载指定包下指定类public class Test {public static void main(String[] args) {Cat one = new Cat();one.run("花花");
// one.setName("花花");
// one.setMonth(2);
// one.setSpecies("英国短毛猫");//静态成员访问方式:1、对象.成员 2、类.成员
// one.price=2000;
// Cat.price=3000;//推荐
// one.run();}
}
输出:
我是构造代码块1
我是宠物猫~
我是静态代码块
我是构造代码块1
我是宠物猫~
我是普通代码块1,temp=12
花花快跑
我是普通代码块2,temp=13
5、总结
static关键字的应用—静态属性
statc是Java中常用的关键字,代表“全局”或者“静态”的意思。关于static的特征,可以理解为:方便在没有创建对象的情况下来进行某些操作。通常可用于修饰成员变量和方法,也可以形成静态代码块。
实际应用中,可将需频数操作、通用型信息设置、公共组件封装等操作设置为“静态”。
应用一:static +成员变量vs 成员变量
概念:
静态成员:用static修饰的成员变量,通常也称为静态成员、静态属性、类成员、全局属性.
非静态成员:没有被static修饰的成员变量,也称为叫做非静态成员、实例变量,实例成员,对象成员、对象属性等。
特征:
静态成员:
- 静态成员属于整个类,由类所进行维护,仅在类初次加时会被初始化,在类销毁时回收
- 通过类实例化的所有对象都共享类中静态资源,任一对象中信息的修订都将影响所有对象
- 由于静态成员在类加载期间就已经完成初始化,存储在Java Heap(JDK7.0之前存储在方法区)中静态存储区,因此优先于对象而存在,可以通过类名和对象名两种方式访问
非静态成员:
- 非静态成员属于对象独有,每个对象进行实例化产生各自的成员,随着对象的回收而释放
- 对象对各自成员信息的修订不影响其他对象
- 只能通过对象名访问
总结:
- 类外可应用“类名.成员名“或”对象名.成员名”的方式访问非私有静态成员,更推荐用“类名.成员名”体现其特性。应用“对象名.成员名”时会出现警告,但不影响程序运行。
- 类内可应用“类名.成员名“或"this.成员名”或“成员”的方式访问,应用"this.成员名”时会出现警告,但不影响程序运行。
static关键字的应用—静态方法
应用二:static +成员方法vs 成员方法
概念:
静态方法:用static修饰的成员方法,通常也称为静态方法、类方法、全局方法等
非静态方法:没有被static修饰的成员方法,也称为叫做非静态方法、实例方法,对象方法等
特征:
与静态成员相似,静态方法属于整个类的,由类所进行维护,优先于对象而存在,因此可以通过类名和对象名两种方式访问,也因此在静态方法中无法直接访问同类中的非静态成员。
总结:
1、静态方法中可以通过“类名.成员”或“成员”的方式访问类内静态成员/静态方法
2、不允许直接访问本类中的非静态成员/非静态方法
3、可以通过实例化产生本类对象,通过“对象.成员”的方式访问类内非静态成员/非静态方法
1、类外可应用“类名.成员方法”或“对象名.成员方法”的方式访问非私有静态方法
2、应用“对象名.成员方法”时会出现警告,但不影响程序运行
1、非静态方法可以通过“类名.成员法”或“成员”或“this.成员”的方式访问类内静态成员/静态方法
2、应用“this.静态成员/静态方法”时会出现警告,但不影响程序运行。
3、不允许在方法内部定义静态局部变量。
static关键字的应用—静态代码块
应用三:static +代码块vs 代码块
概念:
静态代码块:被static修饰的,定义在类内部,用{}括起的代码段。
构造代码块:没有被static修饰的,定义在类内部,用{}括起的代码段。
普通代码块:定义在方法内部,用{}括起的代码段。
特征:
静态代码块:
- 只能出现在类内,不允许出现在方法内。
- 可以出现多次,按顺序在类加载时执行。
- 无论该类实例化多少对象,只执行一次。
构造代码块:
- 可以在类内出现多次,按顺序在每个对象实例化时执行。
- 执行优先级:晚于静态代码块,高于构造方法。
- 每次执行对象实例化时,均会执行一次。
普通代码块:
- 可以在方法内出现多次,按顺序在方法调用时执行。
应用:
- 静态代码块:基于性能优化的考量,多适用于需要在项目启动时执行一次的场景,警如项目资源整体加载等。
- 构造代码块:多适用于类中每个对象产生时都需要执行的功能封装。与构造方法的区别在于,构造方法是在new执行时有选择性的调用带参或者无参构造,而构造代码块则是,在每个对象实例化时都一定会执行。
- 普通代码块:适用于在方法内进行代码功能拆分。
总结:
1、执行优先级:静态代码块>构造代码块>构造方法
2、执行次数:静态代码块只执行1次;构造代码块、构造方法随对象实例化个数而定
1、不能在静态代码块中直接对非静态成员赋值
2、可以在构造代码块中直接操作静态和非静态成员
1、不能在静态代码块声明静态成员,可以声明非静态成员
2、静态代码块中声明的成员,在外部无法进行访问
1、普通代码块在方法内顺序执行,各自作用范围独立
2、方法内定义的局部变量,作用范围为:自定义位置起,至方法结束。在此期间,不允许方法中普通代码块内存在局部变量的声明
三、综合案例:学生信息管理
- 通过方法实现学生与专业关联(3种方案)