看一段代码
import java.util.Scanner;
public class Gril{
public static void main(String[] agrs){
Gril1 gril1=new Gril1();
System.out.print("名字:");
gril1.name=new Scanner(System.in).next();
System.out.print("年龄:");
gril1.age=new Scanner(System.in).nextInt();
if(gril1.age>=18){
System.out.println(gril1.name+"已成年");
}else{
System.out.println(gril1.name+"未成年");
}
}
}
public class Gril1 {
int age;
String name;
}
这是一个简单的判断是否成年的代码,age和name是Gril1的属性。输入输出如下:
但是如果我的输入是不合法的,比如:
这种输入暂且是因为逻辑有问题,改一下if-else的控制条件就好了,但是如果是这样的呢
这样的输入已经超出了整数范围,它直接报错。还有一种情况,因为name是字符串数组,它的长度范围是没有定的,如果我把它写成无限长直接把内存撑爆了,这个程序就有重大bug了。
而且我并不想把age和name这两个成员变量直接暴露出来,就像你走在大街上你应该不希望你的头上顶着你的名字和年龄吧。在日常生活中,有陌生人想知道你的名字,最简单的方法就是开口问你是吧。这里就体现了封装的思想:你的名字和年龄是你的隐私,别人想知道需要通过“问”这种方法。
1.private修饰符的使用
把age和name变成你的隐私就需要用到private修饰符修饰成员变量,这样外部就没有权限访问这个私有变量,只有在这个变量所在的类中才能访问使用。
public class Gril1 {
private int age;
private String name;
}
2.get方法和set方法的声明使用
那么问题来了,既然无法直接在外部访问它那怎么办,我们可以“问”啊,在这个类中写一个getAge方法把变量的值返回。
public class Gril1 {
private int age;
private String name;
int getAge(){
return age;
}
String getName(){
return name;
}
}
至于数据的写入也是通过声明使用成员方法来实现。
public class Gril1 {
private int age;
private String name;
int getAge(){
return age;
}
String getName(){
return name;
}
void setName(String n){
name=n;
}
void setAge(int a){
age=a;
}
}
这里要注意的是,get和set方法的命名是格式要求,以便于别人用你这个封装的类能一眼就看出这个方法是干什么的,不用一行一行的读你的源码。
3.this关键词
为了增加封装类的源码的可读性,我们一般习惯把形参命名得和要修改的私有成员变量的名字一样,比如
public class Gril1 {
private int age;
private String name;
int getAge(){
return age;
}
String getName(){
return name;
}
void setName(String name){
name=name;
}
void setAge(int age){
age=age;
}
}
但是编译器并不能区分此name是不是彼name,默认这个name就是形参,这时就要用到this关键词。
public class Gril1 {
private int age;
private String name;
int getAge(){
return age;
}
String getName(){
return name;
}
void setName(String name){
this.name=name;
}
void setAge(int age){
this.age=age;
}
}
这里的this类似一个指针,指向这个对象在堆中的地址,用“this.”精确指向成员变量。
在主类中实例化该对象,通过对象调用方法就能完成所需的功能了。
import java.util.Scanner;
public class Gril{
public static void main(String[] agrs){
Gril1 gril1=new Gril1();
System.out.print("名字:");
gril1.setName(new Scanner(System.in).next());
System.out.print("年龄:");
gril1.setAge(new Scanner(System.in).nextInt());
if(gril1.getAge()==-1|| gril1.getName()==null){
System.out.println("非法输入");
}else if(gril1.getAge()>=18){
System.out.println(gril1.getName()+"已成年");
}else{
System.out.println(gril1.getName()+"未成年");
}
}
}
class Gril1 {
private int age=-1;
private String name;
int getAge(){
return age;
}
String getName(){
return name;
}
void setName(String name){
if(name.length()<=10) this.name=name;
}
void setAge(int age){
if(age>0) this.age=age;
}
}
测试样例如下
当然,还可以把判断是否成年的方法封装进去,直接调用就行。
封装的好处总结一下就是以下几点:
- 用方法来控制成员变量,提高了代码的安全性
- 把代码封装起来,提高了代码的复用性
- 封装细节,便于修改内部代码,提高可维护性。
- 简化外部调用,便于调用者使用,便于扩展和协作。