【Java入坑之路】子类继承了父类,一定不能直接访问父类的私有属性或者方法吗?


前言

在复习Java面向对象知识点的时候,有一个特征叫做继承。相信很多人都不陌生也能多多少少回答出来。

“子类继承了父类,可以获取父类的所有属性以及方法,但是子类无法访问父类中的private属性或方法

真的是这样的吗?继续往下读吧!


正文

我们直接上测试代码,Test.java文件中的父亲拥有一件XXL的大衣以及一条XXL的秋裤,儿子可以直接获取父亲的物品。

class Father {
    /**
     * 父亲的大衣
     */
    String coat = "XXL的大衣";

    /**
     * 父亲的秋裤
     */
    String johns = "XXL的秋裤";
}

class Son extends Father {
    /**
     * 获取父亲的大衣
     * @return  String
     */
    String getFatherCoat() {
        return super.coat;
    }

    /**
     * 获取父亲的秋裤
     * @return  String
     */
    String getFatherJohns() {
        return super.johns;
    }
}

public class Test {
    public static void main(String[] args) {
        Son son = new Son();
        System.out.println(son.getFatherCoat());
        System.out.println(son.getFatherJohns());
    }
}

运行上面的代码,打印结果如下:

XXL的大衣
XXL的秋裤

秋天来了,父亲想自己拥有秋裤,不想让儿子穿,他把秋裤设为私有的:

private String johns = "XXL的秋裤";

这时儿子就无法获取父亲的秋裤了!IDE报错了:
在这里插入图片描述
那儿子怎样才能得到父亲的秋裤呢?


通过创建public方法访问私有属性(方法)

或许很多人都能想到,就是父类提供一个public访问秋裤的方法,子类直接调用即可。我们在父类中增加一个方法,代码如下:

public String getJohns() {
	return johns;
}

子类直接调用getJohns()方法即可,代码如下:

String getFatherJohns() {
    return super.getJohns();
}

这时确实能够获取父亲的秋裤,但是需要父亲提供给我们一个方法才行,那可不可以直接获取呢?


通过将其定义为内部类,直接获取私有属性(方法)

我们新建一个Test1.java文件,并将父子类添加到Test1中,变成内部类,代码如下:

public class Test1 {
    class Father {
        /**
         * 父亲的大衣
         */
        String coat = "XXL的大衣";

        /**
         * 父亲的私人秋裤
         */
        private String johns = "XXL的秋裤";
    }

    class Son extends Father {
        /**
         * 获取父亲的大衣
         * @return  int
         */
        String getFatherCoat() {
            return super.coat;
        }

        /**
         * 获取父亲的秋裤
         * @return  String
         */
        String getFatherJohns() {
            return super.johns;
        }
    }

    public static void main(String[] args) {
        // 由于Son是内部类,不能直接通过new Son()来获取实例
        Son son = new Test1().new Son();
        System.out.println(son.getFatherJohns());
    }
}

在IDE中竟然没有报错,我们运行一下看看,竟然成功获取了父亲的私人秋裤!
在这里插入图片描述
既然内部类可以直接获取父类的私有属性,那能不能直接调用父类的私有方法呢?

我们在父类中添加一个私有方法获取他本人的秋裤,代码如下:

private String getJohns() {
    return johns;
}

儿子直接调用父类的getJohns(),代码如下:

String getFatherJohns() {
    return super.getJohns();
}

IDE也没有把报错,运行一下代码,确实成功获取到了!
在这里插入图片描述
那不通过子类,而是直接通过父类的实例,也能获取到父类的私有属性吗?

我们再次尝试一下,直接在main方法中添加如下代码:

System.out.println(new Test1().new Father().johns);

发现IDE确实没报错,而且也可以成功运行并打印出父亲的秋裤。
在这里插入图片描述
当然,直接调用父亲的私有方法也是可以的,我们继续在main方法中添加如下代码:

System.out.println(new Test1().new Father().getJohns());

打印结果如下:
在这里插入图片描述
那还有没有其他方式可以直接访问父类的私人秋裤呢?

获取有小伙伴想到了(没有想到的话也配合我一下,假装各位都想到了?),没错就是通过反射!


通过反射获取父类的所有属性(方法)

我们回到Test.java中,在main方法中添加如下代码:

Father father = new Father();
// 获取父亲的类
Class clazz = father.getClass();
// 获取父亲的所有属性
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
    // 设置允许访问私有变量
    field.setAccessible(true);
    try {
    	// 打印父亲的属性信息
        System.out.println("通过反射获得的 " + field.get(father));
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

运行代码,打印结果,可以看到成功打印出父亲的所有属性值,当然包括私有属性:在这里插入图片描述


总结

通过以上测试,我们可以得出:除了定义一个public方法获取私有属性之外,还可以通过下面两种方式直接获取私有属性(方法):

  • 通过将其定义为内部类,直接访问private修饰的属性(方法)
  • 通过反射,并设置允许访问私有属性field.setAccessible(true);

好了,文章到这里也就结束了,南方最近天气转凉,各位小伙伴记得穿秋裤!

发布了57 篇原创文章 · 获赞 282 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/weixin_41463193/article/details/102586746