知识点:
封装 构造方法 this
一、封装
1.1 概述
封装是指隐藏对象的属性和实现细节,仅仅对外提供公共的访问方式。
好处:
1) 提高安全性
2) 提高重用性
1.2 private 关键字
是一个权限修饰符,用于修饰成员变量和成员函数/方法,被私有化的成员只能在本类中访问
1.3 练习 1:封装学生案例
创建 Java 工程: DAY04
创建包: cn.tedu.oop
创建类: Test1_Private.java
package cn.mbh.oop;
/**
*@author MBH:
*@version 创建时间:2022年7月7日 下午1:48:55
*/
/**本类用于测试封装*/
public class Test1_Private {
public static void main(String[] args) {
//通过new关键字创建学生对象,测试
Student s = new Student();
//给变量赋值
s.name = "程序猿";
s.sno = 1;
// s.subject = "java";2.资源被private修饰,本类以外的类是无法访问的
//5.外界通过Studnet类提供的公共设置方法修改subject属性值
s.setSubject("java");
//查看属性值
System.out.println(s.name);
System.out.println(s.sno);
// System.out.println(s.subject);
//6.外界通过Studnet类提供的公共获取方法拿到subject属性值
System.out.println(s.getSubject());
//调用功能
// s.study();//1.资源被private修饰,本类以外的类是无法访问的
s.eat();
}
}
//通过class关键字创建学生类--用来描述学生事物 -- 属性+行为
/* 封装:通过private权限修饰符来修饰成员变量/成员函数/方法
* 被修饰的成员也叫做私有化,访问权限只能在本类中访问*/
class Student{
//属性 -- 成员变量
String name;
int sno;
private String subject;//2.封装成员变量
//3.对外提供公共的设置方式 --- setXxx()
//4.对外提供公共的查看方式 --- getXxx()
public void setSubject(String subject) {
this.subject = subject;
}
public String getSubject() {
return subject;
}
//行为 -- 成员方法
private void study() {
//private void study() {//1.封装成员方法
System.out.println("正在学习");
}
public void eat() {
System.out.println("正在吃饭");
}
}
总结:封装后的资源如何访问?
如何封装?
关于成员变量:用 private 修饰
关于成员方法:用 private 修饰
怎么访问私有资源?
关于成员变量:
1.setXxx()--对外提供公共的设置值方式
2.getXxx()--对外提供公共的获取值方式
关于成员方法:
把私有方法放在公共方法里由外界调用即可
二、构造方法
2.1 概念
构造方法是一种特殊的方法,它是一个与类同名,且没有返回值类型的方法
对象的创建就是通过构造方法来完成的,主要功能是完成对象的创建或者对象的初始化
当类实例化一个对象时会自动调用构造方法
构造方法和其他方法一样也可以重载
eclipse快速生成构造方法:选中要生成的变量,点击alt+Shift+s,找到generate getters and getters
2.2 形式
修饰符 类名 ( [参数列表] ){代码…..}
2.3 练习 2-1:练习构造方法创建对象
创建 Java 工程: DAY04
创建包: cn.tedu.oop
创建类: Test2_Constructor.java
package cn.mbh.oop;
/**
*@author MBH:
*@version 创建时间:2022年7月7日 下午2:19:04
*/
/**本类用于测试构造方法*/
public class Test2_Constructor {
public static void main(String[] args) {
//创建Person对象,测试
//1.每次new对象时(实例化)时会自动调用构造方法
Person p = new Person();
Person p2 = new Person();
}
}
//创建Person类,描述人类事务
class Person{
//属性
String name;
int age;
String address;
//默认存在 无参 构造方法 -- 修饰符 类名(){}
//当new Person()时,自动触发此无参构造
public Person() {
System.out.println("我是Person类的无参构造方法");
}
//行为
public void eat() {
System.out.println("正在吃饭");
}
}
2.3 练习 2-2:练习构造方法赋值
使用类: Test2_Constructor.java
package cn.mbh.oop;
/**
*@author MBH:
*@version 创建时间:2022年7月7日 下午2:19:04
*/
/**本类用于测试构造方法*/
public class Test2_Constructor {
public static void main(String[] args) {
//创建Person对象,测试
//1.每次new对象时(实例化)时会自动调用构造方法
Person p = new Person();
Person p2 = new Person();
//2.创建对象时,会根据参数列表自动匹配使用哪个重载的构造方法
Person p3 = new Person("海绵宝宝");
//3.可以通过构造方法给属性赋值
Person p4 = new Person("派大星",3,"水里");
System.out.println(p4.name);
System.out.println(p4.age);
System.out.println(p4.address);
}
}
//创建Person类,描述人类事务
class Person{
//属性
String name;
int age;
String address;
//1.构造方法:格式:与类同名 + 没有返回值类型 修饰符 类名(){}
//2.构造方法也有重载的现象--方法名相同,参数列表不同
//默认存在 无参 构造方法 -- 修饰符 类名(){}
//当new Person()时,自动触发此无参构造
public Person() {
System.out.println("我是Person类的无参构造方法");
}
//3.当只提供了含参构造,无参构造会被覆盖,没有了,所以创建重载构造方法时,建议手动添加无参构造
//当new Person("")时,自动触发此含参构造方法
public Person(String n) {
System.out.println("我是Pseron类的含参构造方法"+n);
}
//当new Person("", , "")时,自动触发此全参构造方法
public Person(String n,int a,String addr) {
name = n;//n是局部变量,name是成员变量,把用户传的参数值n赋值给成员变量name
age = a;//a是局部变量,age是成员变量,把用户传的参数值a赋值给成员变量age
address = addr;//addr是局部变量,address是成员变量,把用户传的参数值addr赋值给成员变量address
System.out.println("我是Pseron类的全参构造方法"+n+a+addr);
}
//行为
public void eat() {
System.out.println("正在吃饭");
}
}
TIPS: 关于构造函数怎么记忆
特点:没有返回值类型
执行时机:创建对象时立即执行
默认会创建无参构造,但是如果自定义了含参构造,默认的无参构造会被覆盖。
三、综合练习
3.1 练习 3-1:创建 Teacher 类进行 OOP 综合练习之封装
创建类: Test3_Teacher.java
package cn.mbh.oop;
/**
*@author MBH:
*@version 创建时间:2022年7月7日 下午2:30:24
*/
/**本类用于进行OOP综合练习*/
public class Test3_Teacher {
public static void main(String[] args) {
//4.创建对象进行测试
Teacher t = new Teacher();//6.这样创建对象,默认会调用无参构造
//5.由于private将Teacher类中的属性都封装了,外界无法查看,所以通过set()/get()来设置/获取值
t.setAddr("大北京");
t.setName("海绵宝宝");
t.setAge(5);
t.setSalary(100000.0);
//如果没有设置成功,获取的是默认值null/0/0.0
System.out.println(t.getAddr());
System.out.println(t.getAge());
System.out.println(t.getName());
System.out.println(t.getSalary());
//9.直接调用全参构造创建对象,查看属性值是否正常赋值
Teacher t2 = new Teacher("鲁智深",28,10000,"大山头");
System.out.println(t2.getName()+t2.getAge()+t2.getAddr()+t2.getSalary());
}
}
//提供Teacher类
class Teacher{
//属性
//1.利用private关键字封装属性,可见范围:本类
private String name;
private int age;
private double salary;
private String addr;
//行为
//如果什么构造方法都没有提供,默认存在无参构造方法
//如果添加了含参构造,默认的无参构造会被覆盖
public Teacher() {
System.out.println("我是Teacher类的无参构造");
}
public Teacher(String n,int a,double s,String ad) {
//8.可以通过构造方法为成员变量赋值
name = n;
age = a;
salary = s;s
addr = ad;
System.out.println("我是Teacher类的全参构造");
}
//2.向外界提供公共的setXxx() --用来设置值
public void setName(String n) {
name = n;
}
public void setAge(int a) {
age = a;
}
public void setSalary(double s) {
salary = s;
}
public void setAddr(String ad) {
addr = ad;
}
//3.向外界提供公共的getXxx() --用来获取值
public String getName() {
return name;
}
public int getAge() {
return age;
}
public double getSalary() {
return salary;
}
public String getAddr() {
return addr;
}
}
四、this
1.1 概念
this 代表本类对象的一个引用对象
1.2 形式
this . name = name ;
TIPS: this 能点出来的一定是本类的资源,比如成员变量/成员方法
所以等号左边的 this.name 指的就是本类的成员变量 name 属性
4.3 练习 4:this 练习之变量名相同时使用
创建类: Test4_This.java
package cn.mbh.oop;
/**
*@author MBH:
*@version 创建时间:2022年7月7日 下午2:45:44
*/
/**本类用于this练习之变量名相同时使用
* 当一个类中有两个同名变量,一个成员变量一个局部变量
* 想使用本类的成员变量时可以用this指定一下
* */
public class Test4_This {
public static void main(String[] args) {
//创建Cat类对象进行测试
Cat c = new Cat();
c.eat();
}
}
//创建Cat类
class Cat{
int sum = 20;//定义成员变量
int s = 30;
public void eat() {
int sum =10;//局部变量
System.out.println(sum);//10,使用的是局部变量sum
//1.通过this关键字可以用来调用成员变量,前提是:成员变量和局部变量相同时
//如果不使用this指定,那么打印的10,因为变量的就近原则,使用的是局部变量sum
System.out.println(this.sum);//通过this.访问了本类的成员变量sum
System.out.println(s);
}
}
4.4 练习 5:this 练习之构造方法间的调用
创建类: Test5_This2.java
package cn.mbh.oop;
/**
*@author MBH:
*@version 创建时间:2022年7月7日 下午2:49:49
*/
public class Test5_This2 {
public static void main(String[] args) {
//创建对象时会自动调用构造方法
//根据不同的参数触发不同的构造方法
//Dog d = new Dog();//调用无参构造
//Dog d2 = new Dog("小汪");//调用含参构造
Dog d2 = new Dog("汪汪汪");//调用含参构造
}
}
//创建Dog类
class Dog{
/**this可以在构造方法间互相调用
* 但注意是单向的,不是双向来回调用,会死循环*/
//无参构造方法
public Dog() {
//1:需求:在无参构造中 执行含参构造的功能
//2:this关键字在构造方法中的位置必须是第一条语句
//this("小汪汪");
System.out.println("无参构造");
}
//重载的含参构造方法
public Dog(String n) {
//1:在含参构造中 执行 无参构造的功能
//2:this关键字在构造方法中的位置必须是第一条语句
this();
System.out.println("含参构造:"+n);
}
}
五、拓展
5.1 创建对象的流程
1. 把 Person.class 文件加载进内存
2. 在栈内存中,开辟空间,存放引用变量 p
3. 在堆内存中,开辟空间,存放 Person 对象
4. 对成员变量进行默认的初始化
5. 对成员变量进行显示初始化
6. 执行构造方法(如果有构造代码块,就先执行构造代码块再执行构造方法)
7. 堆内存完成
8. 把堆内存的地址值赋值给变量 p ,p 就是一个引用变量,引用了 Person 对象的地址值
5.2 匿名对象
没有名字的对象,是对象的简化表示形式。
使用场景:
1、当被调用的对象只调用一次时(多次会创建多个对象浪费内存)
Demo d = new Demo();d.sleep();d.game();// 这个 d 就是对象的名字。
也可以写成:
new Demo().show();// 创建了一个对象调方法new Demo().game();// 又创建了一个对象调方法