JavaSE基础day07面向对象02匿名、封装、private、getter、setter、JavaBean
一. 面向对象
(一) 匿名对象的使用
1. 概述 : 没有名字的对象
2. 格式 : new 类名(实参);
3. 特点 : 只能使用一次
4. 使用场景:
(1) 如果某个对象在创建之后,其方法只调用一次,那么就可以使用匿名对象来调用。这种写法会节省一些内存空间。
(2) 可以作为某个方法的实际参数。在被调用的方法中,这个对象是有引用的对象,不是匿名对象。
(3) 可以作为某个方法的返回值。这种调用形式,在被调用方法中,这个对象是匿名对象,但是在调用者,这个对象可能不是匿名对象。
5. 优势: 在内存中存在时间短, 相对节省内存
public class Test匿名对象使用 { public static void main(String[] args) { // 有名对象, 名字叫做p Person1 p = new Person1(); // 匿名对象 new Person1(); // 匿名对象与有名对象区别: 有名对象可以反复使用; 匿名对象只能使用一次 p.name = "张三"; p.eat(); new Person1().sleep(); // 为什么要有匿名对象存在? // 如果对于某一个对象的使用, 只用一次(调用成员变量, 调用方法), 那么建议使用匿名对象, 因为一个对象(变量)在内存中如果再也使用不了, JVM就会将这个对象标记成垃圾,很快回收掉, 匿名对象因为在内存存在时间短, 因此相对节省内存使用 } }
匿名对象作为方法参数和返回值结果
public class 匿名对象作为参数和返回值 { public static void main(String[] args) { Person1 per = getPerson(); System.out.println(per); Person1 per1 = new Person1(); usePerson1(per1); // 3. 说明: 匿名对象可以作为方法的实际参数使用 usePerson1(new Person1()); int w = 10; useInt(w); useInt(10); } // 1. 定义出一个方法,返回值结果就是一个Person1类型 public static Person1 getPerson(){ /*Person1 p1 = new Person1(); return p1;*/ // 4. 匿名对象可以作为方法的实际返回值结果 return new Person1();// 0x001 } public static int getInt(){ /*int w = 15; return w;*/ return 15; } // 2. 定义出一个方法,参数是Person1类型,在方法中可以使用Person1 public static void usePerson1(Person1 per){ // 在usePerson1方法中, 可以使用per变量, 相当于可以使用Person1中的功能 per.sleep(); per.eat(); } public static void useInt(int i){ for(int k = 0; k <= i; k++){ System.out.println(k); } }
}
(二) 成员变量和局部变量的区别
1. 定义位置不同
成员变量: 类中方法外
局部变量:方法中
2. 内存位置不同
成员变量:堆空间
局部变量:栈空间
3. 生命周期不同
成员变量:随着类对象的创建而创建,随着对象的消失而消失
局部变量:随着所在方法的执行而创建,随着方法的执行完毕而消失
4. 默认值不同: JVM虚拟机赋初值
成员变量:有默认值
局部变量:没有默认值
// 区分成员变量和局部变量比较 public class Variables { // 1. 定义位置不同: 成员变量定义在类中方法外; 局部变量定义在方法中 // 2. 在内存中存储区域不同: 成员变量跟着对象存储在堆内存中; 局部变量跟着方法存储于栈内存 // 3. 生命周期不同: 成员变量生命与对象一样长; 局部变量生命与方法一样长 // 4. JVM赋初值不同: 成员变量JVM有默认赋初值动作; 局部变量没有JVM默认赋值,要使用局部变量必须先赋值 String name; // 成员变量 public static void main(String[] args) { String str = "abc";// 局部变量 int i; // System.out.println(i); // System.out.println(name); } }
二. 封装
(一) 封装的概述
1. 面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。要访问该类的数据,必须通过指定的方式。适当的封装可以让代码更容易理解与维护,也加强了代码的安全性
2. 封装的原则:
1) 将属性隐藏起来
2) 使用时对外提供公共的访问方式
3. 封装的好处:
1) 隐藏了事物的实现细节
2) 提高了代码的复用性
3) 提高了代码的安全性
(二) private关键字
1. private : 是一个关键字, 私有的意思, 是一个修饰符
2. 修饰内容:
- 修饰成员变量(最常用)
- 修饰成员方法
- 修饰构造方法
- 修饰内部类
3. 修饰效果:
只能在本类中使用,其他所有外类不能直接使用private修饰的成员
public class Animal { String name; // 添加了私有修饰符的成员: 使用范围只能在当前本类中 // age只能在Animal类中使用, 出了Animal类之外, 一律不能直接访问age // private体现出隐藏事物实现细节 封装理念 private int age; }
(三) getter&setter
1. getter方法和setter方法是对属性封装后对外提供的统一访问属性的访问方式
2. 作用:
getXxx():获取封装属性的值
setXxx(参数列表):修改封装属性的值
注意:Xxx代表的是封装属性的名称,首字母大写
public class Animal { String name; // 添加了私有修饰符的成员: 使用范围只能在当前本类中 // age只能在Animal类中使用, 出了Animal类之外, 一律不能直接访问age // private体现出隐藏事物实现细节 封装理念 private int age; // 对age提供对外的公共访问方式 // 对应两个方法 : // 1) setter: 命名方式 set属性名首字母大写; setAge // 功能: 为age成员变量进行赋值 // 2) getter: 命名方式 get属性名首字母大写; getAge // 功能: 获取age 的值 public void setAge(int a){ if(a >= 0 && a <= 50){ age = a; }else { System.out.println("数据输入有误,无法给动物的年龄进行赋值"); } } public int getAge(){ return age; } }
public class TestAnimalPrivate { public static void main(String[] args) { Animal a = new Animal(); a.name = "猫"; public class TestAnimalPrivate { public static void main(String[] args) { Animal a = new Animal(); a.name = "猫"; // a.age = 5; Animal a1 = new Animal(); a.name = "狗"; // a.age = -6; // 发现: 当给成员赋值,直接赋值和访问方式造成数据不安全(不符合条件) // 因此想不然外界直接访问age属性, 可以在age属性前, 添加一个关键字: 修饰符 private 私有的 /*int age = 999; if(age >= 0 && age <= 50){ a.age = age; }*/ Animal a2 = new Animal(); a2.setAge(-9); System.out.println(a2.getAge()); Animal a3 = new Animal(); a3.setAge(9); System.out.println(a3.getAge()); } }
(四) 封装优化
把封装后对相关操作的修改操作称之为封装的优化
4.1变量的访问原则
1. 总体原则:就近访问原则
2. 就近访问:
当在访问某个变量名称的时候,会先寻找最近的该变量名称的定义,如果寻找到了,就使用该变量,如果没有找到,才到更远的位置寻找该变量名称的定义。
比如:
当局部变量和成员变量同名的时候,一定是先使用局部位置定义的变量
4.2 this关键字
1. this关键字含义:代表所在类的当前对象的引用(地址值),即对象自己的引用。
2. this关键字作用:
(1) 当成员变量和局部变量重名, 带有this关键字的变量表示成员变量的使用
(2) 开发中, setter方法中局部变量和成员变量同名赋值失败的问题就可以使用this关键字来解决
(3) 哪个对象调用了带有this关键字的方法, this关键字就表示哪个对象本身
public class 变量访问原则 { // 成员变量 : 跟着对象存在于堆内存 int i = 10; public void useI(){ // 局部变量跟着方法存在于栈内存 int i = 20; // 1. 变量访问: 就近原则; 当使用一个变量时, 选择最近的一次变量定义位置 // 如果有局部变量,优先; 没有局部变量,找成员变量 System.out.println(i);// 20 // 2. this: 关键字,表示本类对象引用 // this使用场景之一: 可以区分成员变量和局部变量重名问题, 带有this关键字的变量表示成员变量的调用 // this: 哪个对象调用了带有this关键字的方法, 那么this就表示哪个对象本身 System.out.println(this.i);// 10 System.out.println(this + "------"); } public static void main(String[] args) { 变量访问原则 demo = new 变量访问原则(); System.out.println(demo); demo.useI(); System.out.println(demo.i);// 10 变量访问原则 demo1 = new 变量访问原则(); System.out.println(demo1+ "~~~~~~~~~~~~~~~~~"); demo1.useI(); } }
this关键字内存理解:
this关键字在setter方法中的使用
public class Cat { private String name; private int age; // alt + insert: 快捷键, 可以辅助生成中方法 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; } }
(五) 构造方法
1. 构造方法概述: 当一个对象被创建时,构造方法用来初始化该对象,给对象的成员变量赋初始值。构造方法有自己独有的方法格式。
2. 构造方法分类: 有参构造, 无参构造
3. 构造方法定义格式:
修饰符 构造方法名(参数列表){
// 方法体,主要就是给对象中成员变量进行赋值
}
4. 构造方法特点:
1) 方法名必须和类名一致
2) 没有返回值类型,连void都不写
3) 默认被jvm调用使用, 构造方法调用时机:
在创建对象时, JVM虚拟机主动调用,并且创建一次对象, 构造方法只调用一次, 构造方法无法手动通过对象名调用
5. 注意事项:
1) 如果不提供构造方法,系统会给出无参数构造方法。
2) 如果提供了构造方法,系统将不再提供无参数构造方法。
3) 构造方法是可以重载的,既可以定义参数,也可以不定义参数。
如果代码中定义了空参数构造, 也同时定义了有参数构造, 那么创建对象时, 可以从多个构造中选择其中任意一个调用即可
public class Student { private String classNo; private String schoolName; /* 构造方法定义: 修饰符 构造方法名(参数列表){ 主要功能就是给当前对象的成员变量进行赋值; } 1. 修饰符: 通常情况下都是public 2. 构造方法没有返回值结果, 连void不写 3. 构造方法名必须与类名一致 4. 构造要功能就是给当前对象的成员变量进行赋值 构造方法运行时机: 每次创建对象的同时, JVM虚拟机主动调用构造方法一次; 构造方法不能手动调用的 */ /*public Student(){ System.out.println("我是一个空参数构造方法"); } public Student(String classNo, String schoolName){ this.classNo = classNo; this.schoolName = schoolName; }*/ /* 构造方法使用注意事项: 1. 如果类型中没有手动定义任何构造, JVM虚拟机会默认的生成一个空参数构造 public Student(){} 2. 如果手动在类型中添加了构造,不论空参还是有参, JVM不会再为类型提那家其他构造 3. 构造方法可以重载 方法重载: 定义在同一个类中,方法名相同, 参数列表不同, 与方法出的返回值类型无关 4. 如果在类型中添加了有参数构造, 请一定要将空参数构造添加上 5. alt + inset: 快捷键,可以自动生成构造方法 */ public Student() { } public Student(String classNo, String schoolName) { this.classNo = classNo; this.schoolName = schoolName; } public Student(String schoolName) { this.schoolName = schoolName; } public String getClassNo() { return classNo; } public void setClassNo(String classNo) { this.classNo = classNo; } public String getSchoolName() { return schoolName; } public void setSchoolName(String schoolName) { this.schoolName = schoolName; } }
public class StudentConstructor { public static void main(String[] args) { // 数据类型 对象名 = new 数据类型(); // 对象创建过程中, ()就表示构造方法的调用 Student s = new Student(); Student s1 = new Student(); Student s2 = new Student(); // 构造方法作用: 创建对象完毕,这个对象中的成员变量就有值了 Student s3 = new Student("3年2班","北关小学"); System.out.println(s3.getClassNo()); System.out.println(s3.getSchoolName()); Student s4 = new Student("3年3班","十堰小学"); System.out.println(s4.getClassNo()); System.out.println(s4.getSchoolName()); } }
(六) 标准JavaBean
JavaBean是Java语言编写类的一种标准规范。符合JavaBean 的类,要求
1. 类必须是具体的和公共的
2. 所有属性使用private修饰
3. 提供用来操作成员变量的set 和get 方法
4. 并且具有有参数的构造方法(建议有)
格式:
public class ClassName{
//成员变量【必须封装】
//构造方法
//无参构造方法【必须】
//有参构造方法【建议】
//成员方法
//getXxx()
//setXxx()
(七)扩展:
基本数据类型作为方法参数传递
引用数据类型作为方法参数传递: