封装
什么是封装
在我们写代码的时候经常会涉及两种角色: 类的实现者和类的调用者。
封装的本质就是让类的调用者不必太多的了解类的实现者是如何实现类的, 只要知道如何使用类就行了。这样就降低了类使用者的学习和使用成本, 从而降低了复杂程度。
private实现封装
private/ public 这两个关键字表示 “访问权限控制”。
- 被 public 修饰的成员变量或者成员方法, 可以直接被类的调用者使用。
- 被 private 修饰的成员变量或者成员方法, 不能被类的调用者使用。
换句话说, 类的使用者根本不需要知道, 也不需要关注一个类都有哪些 private 的成员. 从而让类调用者以更低的成本来使用类。
使用public
class Person {
public String name;
public int age;
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();
person.name = "jj";
person.age = 18;
System.out.println(person.name);
System.out.println(person.age);
}
}
缺点:
- 这样的代码导致类的使用者(main方法的代码)必须要了解 Person 类内部的实现, 才能够使用这个类. 学习成本较高。
- 一旦类的实现者修改了代码(例如把 name 改成 myName), 那么类的使用者就需要大规模的修改自己的代码, 维护成本较高。
使用private
class Person {
private String name;
private int age;
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;
}
}
public class TestDemo {
public static void main(String[] args) {
Person person = new Person();
person.setName("jj");
person.setAge(18);
System.out.println(person.getName());
System.out.println(person.getAge());
}
}
优点:
- 此时字段已经使用 private 来修饰. 类的调用者(main方法中)不能直接使用. 而需要借助 getName、getAge、setName、setAge 方法. 此时类的使用者就不必了解 Person 类的实现细节。
- 同时如果类的实现者修改了字段的名字, 类的调用者不需要做出任何修改(类的调用者根本访问不到 name, age这样的字段)。
注意事项:
- private 不光能修饰字段, 也能修饰方法
- 通常情况下我们会把字段设为 private 属性, 但是方法是否需要设为 public, 就需要视具体情形而定. 一般我们希望一个类只提供 “必要的” public 方法, 而不应该是把所有的方法都无脑设为 public。
getter和setter方法
我们在前面看到setName、getName、setAge、getAge就是getter和setter方法,getName 即为 getter 方法, 表示获取这个成员的值,setName 即为 setter 方法, 表示设置这个成员的值。因为我们无法直接获取被private修饰的成员变量,所以我们只能通过getter和setter方法。当然也有几点需要注意:
- 当set方法的形参名字和类中的成员属性的名字一样的时候,如果不使用this, 相当于自赋值. this 表示当前实例的引用。
- 不是所有的字段都一定要提供 setter / getter 方法, 而是要根据实际情况决定提供哪种方法。
- 在 IDEA 中可以使用 alt + insert (或者 alt + F12) 快速生成 setter / getter 方法. 在 VSCode 中可以使用鼠标右键菜单 -> 源代码操作 中自动生成 setter / getter 方法。
构造方法
基本语法
构造方法是一种特殊方法, 使用关键字new实例化新对象时会被自动调用, 用于完成初始化操作。所以new一个对象会有两个过程:1.为对象分配内存空间
2.调用对象的构造方法
语法规则
- 如果类中没有提供任何的构造函数,那么编译器会默认生成一个不带有参数的构造函数。(也就是说构造方法是一个类必须的,如果没有写构造方法,编译器也会生成一个)
- 若类中定义了构造方法,则默认的无参构造将不再生成。
- 构造方法支持重载. 规则和普通方法的重载一致。(什么是重载?可以看这篇博客:方法的使用)
举个例子:
class Person {
public String name;
public int age;
public Person() {
System.out.println("调用Person()方法:不带参数");
}
public Person(String name) {
this.name = name;
System.out.println("调用Person()方法:带一个参数");
}
public Person(String name ,int age){
this.name = name;
this.age=age;
System.out.println("调用Person()方法:带二个参数");
}
}
public class TestDemo {
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("====================");
Person person2=new Person("jj");
System.out.println("====================");
Person person3=new Person("jj",11);
}
简而言之,当我们new一个对象时,会分配给对象空间,并且调用合适的构造方法,调用哪个构造方法是根据传的参数的个数和类型决定的。
this关键字
his表示当前对象引用(注意不是当前对象)。因此他有3种用途:
- 调用当前对象的属性——this.date
- 调用当前对象的方法——this.func()
- 调用当前对象的其他构造方法——this()
举个例子:
class Person {
private String name;//实例成员变量
private int age;
private String sex;
//默认构造函数 构造对象
public Person() {
//this调用构造函数
this("bit", 12, "man");//必须放在第一行进行显示
}
//这两个构造函数之间的关系为重载。
public Person(String name,int age,String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public void show() {
System.out.println("name: "+name+" age: "+age+" sex: "+sex);
}
}
public class Main{
public static void main(String[] args) {
Person person = new Person();//调用不带参数的构造函数
person.show();
}
}
有关封装和构造方法的知识就到这里,如果有什么问题或者建议欢迎各位私信或者评论,谢谢大家!