Java能不能继承父类的protected和private方法?

Java能不能继承父类的protected和private方法?

子父类定义

  1. 先写一个父类,定义方法和变量
public class Father {
    public String fatherPublicString = "father public";
    protected String fatherProtectedString = "father protected";
    private String fatherPrivateString = "father private";

    public void fatherPublicMethod(){
        System.out.println("father public method");
    }

    protected void fatherProtectedMethod(){
        System.out.println("father protected method");
    }

    private void fatherPrivateMethod(){
        System.out.println("father private method");
    }
  1. 之后再写一个子类,定义方法和变量
public class Child extends Father {
    public String childPublicString = "child public";
    protected String childProtectedString = "child protected";
    private String childPrivateString = "child private";
    public void childPublicMethod() {
        System.out.println("child public method");
    }
    protected void childProtectedMethod() {
        System.out.println("child protected method");
    }
    private void childPrivateMethod() {
        System.out.println("child private method");
    }
}
  1. 然后我们先看一下值子类能不能继承父类的一些共有私有属性
    • 我们使用getDeclaredFields()和getFields()方法,想来看一下JDK帮助文档怎么定义者两个方法的
      * getFields() *
      返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
      * getDeclaredFields() *
      返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段
    • JDK帮助文档写的很清楚了,我就不再做解释了,主要看看getDeclaredFields()能不能获得父类的私有属性
    • 代码
//遍历Field数组
public static void iteratorField(Field[] fields) {
        for (Field field : fields) {
            System.out.println(field.getName());
        }
        System.out.println("-------------------------");
    }
Class<?> childClass = Class.forName("com.reflection.Child");
Client.iteratorField(childClass.getFields());
Client.iteratorField(childClass.getDeclaredFields());
  • 摸摸搭,我们来看一下结果
    //getFields
    childPublicString 
    fatherPublicString
    -------------------------
    //getDeclaredFields
    childPublicString
    childProtectedString
    childPrivateString
    -------------------------
  • 结果让我很失望,表示使用getFields将继承的public共有属性给弄过来了,虽然getDeclaredFields将private属性和protected属性也获得到了,但是他居然没有得到从父类继承下来的public共有属性!!虽然APi说的很清楚,但是这样的话怎么对父类的属性进行处理呢??还有protected属性应该也是能够获得的啊,没办法,换方法.
    try {
            System.out.println(name +" field " +class1.getField(name));
            System.out.println("-------------------------");
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            System.out.println(e.getMessage() + " NoSuchFieldException");
        }

        try {
            System.out.println(name +" declaredField " +  class1.getDeclaredField(name));
            System.out.println("---------------------------------------------");
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            System.out.println(e.getMessage() + " NoSuchFieldException");
        }

    Client.getField(childClass, "fatherPublicString");
    Client.getField(childClass, "fatherProtectedString");
    Client.getField(childClass, "fatherPrivateString");
  • 结果…..还是没有办法得到啊,怎么破?
    fatherPublicString field public java.lang.String com.reflection.Father.fatherPublicString
    ---------------------------------------------------------------------------------------
    fatherPublicString NoSuchFieldException
    fatherProtectedString NoSuchFieldException
    fatherProtectedString NoSuchFieldException
    fatherPrivateString NoSuchFieldException
    fatherPrivateString NoSuchFieldException
  • 没办法只有用getSuperClass()获得父类了
    //其他方法不变
    Client.getField(childClass.getSuperclass(), "fatherPublicString");
    Client.getField(childClass.getSuperclass(), "fatherProtectedString");
    Client.getField(childClass.getSuperclass(), "fatherPrivateString");

    //结果getDeclaredField方法正常拿到父类的public,protected,private属性
    fatherPublicString field public java.lang.String com.reflection.Father.fatherPublicString
    -------------------------
    fatherPublicString declaredField public java.lang.String com.reflection.Father.fatherPublicString
    ---------------------------------------------
    fatherProtectedString NoSuchFieldException
    fatherProtectedString declaredField protected java.lang.String com.reflection.Father.fatherProtectedString
    ---------------------------------------------
    fatherPrivateString NoSuchFieldException
    fatherPrivateString declaredField private java.lang.String com.reflection.Father.fatherPrivateString
    ---------------------------------------------
  • 好吧,我也是心醉了,都继承了,我还拿不到父类的private,protected对象,非的我从父类拿,QAQ,这个先放一放,看看Method能给我们带来什么惊喜

Method的private,protected,private方法探讨

  • 还是一样,我们通过getDeclaredMethods()和getMethods()来获得Method方法,一下是这两个方法的定义
    * getMethods() *
    返回一个包含某些 Method 对象的数组,这些对象反映此 Class对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
    * getDeclaredMethods() *
    返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
  • 人家都告诉你了可以有从超类上继承的东东,看来有希望了,我们测试下:
    //获得的Method方法迭代打出
    public static void iteratorMethods(Method[] methods){
        for(Method method : methods){
            System.out.println(method.getName());
        }
        System.out.println("---------------------------------------------");
    }
//客户端调用,我调!我调!
Class<?> childClass = Class.forName("com.reflection.Child");
Client.iteratorMethods(childClass.getMethods());
Client.iteratorMethods(childClass.getDeclaredMethods());
  • 结果ing…..
    childPublicMethod
    fatherPublicMethod
    wait
    wait
    wait
    hashCode
    getClass
    equals
    toString
    notify
    notifyAll
    ---------------------------------------------
    childPublicMethod
    childProtectedMethod
    childPrivateMethod
    ---------------------------------------------
  • 俺内心是拔凉拔凉的…………..,也是只能得到子类的一些方法,继承的protected, private呢?!我们获得他的父类,打印一下看看
    fatherPublicMethod
    wait
    wait
    wait
    hashCode
    getClass
    equals
    toString
    notify
    notifyAll
    ---------------------------------------------
    fatherPublicMethod
    fatherProtectedMethod
    fatherPrivateMethod
    --------------------------------------------
  • 好吧,内心到了低谷,和Field是一样的…..,带参数的getMethod()和getDeclaredMethod()我就不测试了,结果是差不多的.这样我们就得到了一些疑问
    继承到底继承了一些什么属性?private被继承了么?
    那就是继承的protected,为什么能够在子类被调用,但是不能够在反射中获得呢?

问题解决

  1. 第一个问题,感谢老外,我找到了一段对这个的解释
    Oracle tutorial

    A subclass inherits all of the public and protected members of its parent, no matter what package the subclass is in. If the subclass is in the same package as its parent, it also inherits the package-private members of the parent.
    You can use the inherited members as is, replace them, hide them, or supplement them with new members。
    A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.
    A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited by a subclass has indirect access to all of the private members of the superclass.

    • 子类继承了父类的所有的public和protected方法,无论子类是不是和父类在一个包中,如果子类和父类在一个包中,他也继承了他的private成员(哥哥这不是纠缠不清么,等会看下面的)。
    • 你可以使用继承的成员去替换他,隐藏他,或者补充新成员。
    • 子类没有继承父类的private成员变量。不过,如果子类的public或者protected成员变量能够访问这些私有变量,他们(public, protected包装的private, 类似就是JavaBean一样)可以被子类使用。
    • 内部类可以访问类的(就是在A类中的B类是内部类,B可以访问A的private)所有的private成员变量.因此一个public或者是protected的内部类可以被子类,可以间接访问所有父类的私有成员变量.
    • 大家仔细想一下,内部类本来就只能在定义他的类中被调用(我指的是继承,A.B调用,不算),那么访问他的私有变量也是可以得。
      为什么呢,大家看一下我这个程序吧,这里主要是内部类的继承了private的表现,如果感兴趣可以跑一下,结果是可行的.
public class Child extends Father {
    public String childPublicString = "child public";
    protected String childProtectedString = "child protected";
    private String childPrivateString = "child private";

    public void childPublicMethod() {
        System.out.println("child public method");
    }

    protected void childProtectedMethod() {
        System.out.println("child protected method");
    }

    private void childPrivateMethod() {
        System.out.println("child private method");
    }

    public class GrandChildren{

        public String grandChildrenPublicString = "grandChildren public";
        protected String grandChildrenProtectedString = "grandChildren protected";
        private String grandChildrenPrivateString = "grandChildren private";

        public GrandChildren(){
            super();
        }
        public void grandChildrenPublicMethod() {
            System.out.println("grandChildren public method");

            //包含类的私有方法可以被访问
            childPrivateMethod();
        }

        protected void grandChildrenProtectedMethod() {
            System.out.println("grandChildren protected method");
            //包含类的protected方法也可以被访问
            childProtectedMethod();
        }

        private void grandChildrenPrivateMethod() {
            System.out.println("grandChildren private method");
        }
    }

    public class GreatGrandChildren extends GrandChildren{
        //关键是这里,使用了父类的private变量,编译通过,可以访问
        private String greatGrandChildrenPrivateString = super.grandChildrenPrivateString;
        private String greatGrandChildrenProtectedString = super.grandChildrenProtectedString;
        private String greatGrandChildrenPublicString = super.grandChildrenPublicString;

        public void greatGrandChildrenPublicMethod() {
            super.grandChildrenPublicMethod();
        }

        protected void greatGrandChildrenProtectedMethod() {
            //同样,protected方法可以访问
            super.grandChildrenProtectedMethod();
        }

        private void greatGrandChildrenPrivateMethod() {
            //private方法也可以访问
            super.grandChildrenPrivateMethod();
        } 
    }
}

那我最后就可以得到一个结论: 继承的话,private, protected都会被继承下来,private只有内部类,才会对其暴露.或者是被包装的protected,public包装的private可以被访问(话说有这么用么?这不是自己找罪受么?)

  1. 第二个问题,其实我这个问题有点错误,其实可以从反射中获得,只不过方法不是那么直接罢了,我们看下面的程序
private static Field getField(Class clazz, String fieldName) throws NoSuchFieldException {
    try {
        return clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
        //子类得不到,我们就从父类拿喽!
        Class superClass = clazz.getSuperclass();
        if (superClass == null) {
        throw e;
        } else {
        return getField(superClass, fieldName);
        }
    }
}

获得method方法也是如此,子类的得不到就一直遍历,查找父类,获得想要的Field or Method.

总结


  • public , protected是会被子类继承的,private的继承有条件—内部类
  • 父类的protected,private的Field和Method没有办法被直接得到,只有通过递归遍历superClass进行查找
  • 以后我们写程序的时候如果需要修改protected或者是private值,尽量为其创建一个public的set方法,方便反射调用(这也很好的解释了spring的注入,一开始建议不要写在Field上)
  • 用MarkDown还是不太熟练,以后注意一下HTML标签,Sublime和CSDN的编辑器还不一样,郁闷,多谢谢吧!^_^
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值