为什么要使用private
出于 安全性考虑,我们在写字段时,尽量考虑采用 封装,这样可以隐藏类的细节,只对外开放接口即可实现对象之间的交互。
一、 定义
- private关键字是一个访问修饰符
- 修饰范围:
- 修饰成员变量
表示当前成员变量只能在当前类中使用 - 修饰成员方法
表示当前成员方法只能在当前类中使用
- 修饰成员变量
二、private代码示例
下面是一个GirlFriend类,有三个属性name、age、gender分别被private修饰,有两个成员方法sleep()、eat()。也分别被private修饰。
public class GirlFriend {
private String name;
private int age;
private String gender;
private void sleep(){
System.out.println("正在睡觉");
}
private void eat(){
System.out.println("正在吃饭");
}
}
下面是一个GirlFriendTest类,创建了GirlFriend类的实例对象,并且想要调用GirlFriend类中的属性,但由于GirlFriend类中的成员变量被private修饰了因此对象没办法调用
public class GirlFriendTest1 {
public static void main(String[] args) {
GirlFriend girlFriend1 = new GirlFriend();
//编译无法通过,因为String name 属性被 private修饰
girlFriend1.name;
}
}
就算是Girlfriend的子类的实例对象也是不能够去调用的
下面有一个GirlFriend的子类ExtendGirlFriend,测试类中创建ExtendGirlFriend的实例对象并调用ExtendGirlFriend父类的成员变量
public class ExtendGirlFriend extends GirlFriend{
public String height;
}
public class GirlFriendTest1 {
public static void main(String[] args) {
ExtendGirlFriend extendGirlFriend = new ExtendGirlFriend();
//编译无法通过,因为String name 属性被 private修饰
extendGirlFriend.name="小诗诗";
}
}
三、如何让其他类使用到private的成员变量
我们可以创建一个 public 方法,在方法里 仅return 被private修饰的变量;另一个public方法可以用来对private修饰的变量进行赋值
也就是使用Getter and setter方法
可以使用快捷键进行创建:Alt+Insert -> Getter and setter
如下代码通过Getter and setter后可以让其他类使用到private的成员变量了
public class GirlFriend {
private String name;
private int age;
private String gender;
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 String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
测试类中:创建GirlFriend类的实例对象后,可以通过调用对象的set方法去设置对象的private成员变量,通过get方法可以得到设置后的值
public class GirlFriendTest1 {
public static void main(String[] args) {
GirlFriend girlFriend = new GirlFriend();
girlFriend.setName("小诗诗");
girlFriend.setAge(18);
girlFriend.setGender("女");
int age = girlFriend.getAge();
System.out.println(age);
}
}
注意点:比如设置年龄时候设置了-18,这其实是不符合规定的,因为年龄必须大于0岁,我们通过这种get和set方法就可以在方法内加上一些规范,从而避免出现这种问题,从而提高代码的健壮性
public void setAge(int age) {
if (age<0){
System.out.println("输入的年龄不可小于0岁");
}else {
this.age = age;
}
}
//下面在进行调用setAge方法时候就会进行判断年龄是否符合要求
public class GirlFriendTest1 {
public static void main(String[] args) {
GirlFriend girlFriend = new GirlFriend();
girlFriend.setName("小诗诗");
girlFriend.setAge(-18);
girlFriend.setGender("女");
int age = girlFriend.getAge();
System.out.println(age);
}
}
四、如何其他类调用private修饰的成员方法
1、使用公共方法间接调用
通过以上的调用private修饰的成员变量的使用,那么可以采用同样的方式,可以在类中创建一个public方法,方法中调用private修饰的成员方法,然后其他类就可以调用这个public方法从而实现了调用private修饰的成员方法
如下GirlFriend 类中有一个sleep方法,被private修饰,已知测试类直接通过对象并不能调用,在GirlFriend 类中,又有一个getSleepf方法是被public修饰的,getSleep调用了sleep方法,测试类中可以通过对象调用getSleep方法从而调用了private修饰的sleep方法
public class GirlFriend {
private void sleep(){
System.out.println("正在睡觉");
}
public void getSleep(){
sleep();
}
}
//测试类
public class GirlFriendTest1 {
public static void main(String[] args) {
GirlFriend girlFriend = new GirlFriend();
girlFriend.getSleep();
}
}
//最后打印结果:正在睡觉
2、 通过反射调用
通过Java的反射机制,可以在其他类中调用私有方法。
反射允许对成员变量、成员方法和构造方法的信息进行编程访问。说白了,反射就是可以从类里边拿东西
以下有一个GirlFriend 类和一个测试类,GirlFriend 类中有一个被private修饰的sleep方法
测试类中创建了GirlFriend 的对象,但是已知直接 对象.sleep() 是没办法调用的。通过反射的机制是可以在Class字节码文件对象中获取到private修饰的成员方法
- 首先获取到Class字节码文件对象
- 用该字节码文件对象的getDeclaredMethod()方法可以获取单个指定的方法,传递参数为方法名
- 需要注意的是,通过反射调用私有方法需要在调用之前将私有方法的可访问性设置为true,否则会抛出异常
- 使用invoke方法可以进行运行要调用的方法,invoke要传递的参数有两个,一个是想要调用sleep方法的对象,另一个是sleep中要传递的实际参数,当然sleep中没有形参就不用在invoke中写了
//GirlFriend 类:
public class GirlFriend {
private void sleep(){
System.out.println("正在睡觉");
}
}
//测试类:
public class GirlFriendTest1 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
GirlFriend girlFriend = new GirlFriend();
//1. 首先获取Class字节码文件对象 ( 对象.getClass()的方式获取Class对象 )
Class aClass = girlFriend.getClass();
//2. 通过getDeclaredMethod()方法获取指定的单个成员方法(要抛出异常)
Method sleep = aClass.getDeclaredMethod("sleep");
//3.通过反射调用私有方法需要在调用之前将私有方法的可访问性设置为true,临时取消方法的访问权限
sleep.setAccessible(true);
/*
4. 使用invoke方法可以进行运行,invoke()中有两个参数
参数一:obj对象调该方法
参数二:sleep方法要传递的参数(没有就不写)
*/
sleep.invoke(girlFriend);
}
}
总之,私有方法主要用于封装内部实现细节,不建议直接在其他类中调用。如果确实有需要,可以通过间接调用或者反射来实现