如何在其子类中访问类的私有变量?

时间:2010-02-13 20:18:27

标签: java core

这是我在接受采访时被问到的一个问题:我有A级私人成员,B级扩展A.我知道一个班级的私人成员无法访问,但问题是:我需要访问私人成员B类中的A类,而不是在B类中创建具有相同值的变量。

28 个答案:

答案 0 :(得分:34)

面试官要么测试你对访问修饰符的了解,要么是你改变现有类的方法,或两者​​兼而有之。

我会列出它们(公共的,私有的,受保护的,包私有的)以及每个的解释。然后继续说A类需要被修改以允许通过添加setter和getter,或者通过更改成员的访问修饰符来访问B类中的那些成员。或者B类可以使用反射。最后,谈谈每种方法的利弊。

答案 1 :(得分:11)

反射?省略进口,这应该有效:

public class A {

    private int ii = 23;

}

public class B extends A {

    private void readPrivateSuperClassField() throws Exception {
        Class<?> clazz = getClass().getSuperclass();
        Field field = clazz.getDeclaredField("ii");
        field.setAccessible(true);
        System.out.println(field.getInt(this));
    }

    public static void main(String[] args) throws Exception {
        new B().readPrivateSuperClassField();
    }

}

如果你在调用readPrivateSuperClassField();之前做了类似的事情,它将无效:

System.setSecurityManager(new SecurityManager() {
        @Override
        public void checkMemberAccess(Class<?> clazz, int which) {
            if (clazz.equals(A.class)) {
                throw new SecurityException();
            } else {
                super.checkMemberAccess(clazz, which);    
            }
        }
    });

还有其他条件,反思方法不起作用。有关详细信息,请参阅the API docs for SecurityManagerAccessibleObject。感谢CPerkins指出这一点。

我希望他们只是测试你的知识,而不是寻找这些东西的真实应用;-)虽然我认为像上面这样丑陋的黑客在某些边缘情况下是合法的。

答案 2 :(得分:6)

架构坏了。私人会员是私人会员,因为您不希望他们在课堂和朋友之外访问。

您可以使用朋友黑客,访问者,推广会员或#define private public(嘿)。但这些都是短期解决方案 - 你可能不得不在某个阶段重新审视破碎的架构。

答案 3 :(得分:6)

使用A的私人成员的公共访问者(getter&amp; setters)......

答案 4 :(得分:5)

您无法从父类访问私有成员。您已使其受保护或具有可访问它们的受保护/公共方法。

编辑:您可以使用反射。但这不是常见的,也不是打破封装的好主意。

答案 5 :(得分:3)

嵌套类可以访问其封闭类的所有私有成员 - 包括字段和方法。因此,子类继承的公共或受保护嵌套类可以间接访问超类的所有私有成员。

public class SuperClass
{
    private int a = 10;
    public void makeInner()
    {
        SubClass in = new SubClass();
        in.inner();
    }
    class SubClass
    {
        public void inner()
        {
            System.out.println("Super a is " + a);
        }
    }
    public static void main(String[] args)
    {
        SuperClass.SubClass s = new SuperClass().new SubClass();
        s.inner();
    }
}

答案 6 :(得分:2)

如果我正确理解了问题,您可以将private更改为protected。受保护的变量可供子类访问,但其行为类似于私有变量。

答案 7 :(得分:2)

通过使用setter和getters,你可以访问它

答案 8 :(得分:2)

来自JLS §8.3. Field Declarations

  

子类可以访问超类的私有字段 - 例如,如果两个类都是同一个类的成员。然而,私有字段永远不会被子类继承。

我写了示例代码:

public class Outer
{
    class InnerA
    {
        private String text;
    }
    class InnerB extends InnerA
    {
        public void setText(String text)
        {
            InnerA innerA = this;
            innerA.text = text;
        }
        public String getText()
        {
            return ((InnerA) this).text;
        }
    }
    public static void main(String[] args)
    {
        final InnerB innerB = new Outer().new InnerB();
        innerB.setText("hello world");
        System.out.println(innerB.getText());
    }
}

InnerA.text的可访问性解释在JLS §6.6.1. Determining Accessibility

  

否则,成员或构造函数被声明为private,并且当且仅当它发生在包含成员或构造函数声明的顶级类(第7.6节)的主体内时才允许访问。

答案 9 :(得分:1)

您是否考虑过让他们受保护?只是为了确保你知道这个选项,如果你当时原谅我提出这个琐事;)

答案 10 :(得分:1)

  • 私人成员无法在派生类
  • 中访问
  • 如果您想要访问意味着您可以使用getter和setter方法。
class A
{
 private int a;
 void setA(int a)
 {
    this.a=a;
 }
 int getA()
 {
   return a;
 }
}

Class B extends A
{
 public static void main(String[] arg)
  {
     B obj= new B();
     obj.setA(10);
     System.out.println("The value of A is:"+obj.getA());
  } 
}

答案 11 :(得分:1)

你可以使用A类的setter和getter。它给人的感觉就像使用A类的对象一样。

答案 12 :(得分:0)

下面是访问子类对象中超类的私有成员的示例。

我正在使用构造函数来做同样的事情。

以下是超类Fruit

public class Fruit {
    private String type;

    public Fruit() {
    }

    public Fruit(String type) {
        super();
        this.type = type;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

}

下面是继承自Fruit

的子类Guava
public class Guava extends Fruit{
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Guava(String name,String type) {
        super(type);
        this.name=name;
    }
}

下面是我们创建子类对象并显示超类成员的主要功能。

public class Main {

    public static void main(String[] args) {

        Guava G1=new Guava("kanpuria", "red");
        System.out.println(G1.getName()+" "+G1.getType());

    }

}

答案 13 :(得分:0)

您可能希望将其更改为受保护。 请参考此

https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

如果这是你必须做的事情,只是为了做到这一点你可以使用反射。它将为您提供类中定义的所有变量的列表 - 公共,私有或受保护。这肯定有它的开销,但是,它是让你使用私有变量的东西。有了这个,你可以在任何一个类中使用它。它不必只是一个子类 请参考下面的示例。这可能有一些编译问题,但你可以得到基本的想法,它的工作原理

private void getPropertiesFromPrivateClass(){

    Field[] privateVariablesArray = PrivateClassName.getClass().getDeclaredFields();
    Set<String> propertySet = new HashSet<String>();
    Object propertyValue;
    if(privateVariablesArray.length >0){
        for(Field propertyVariable :privateVariablesArray){
            try {

                if (propertyVariable.getType() == String.class){
                    propertyVariable.setAccessible(true);
                    propertyValue = propertyVariable.get(envtHelper);
                    System.out.println("propertyValue");
                }
            } catch (IllegalArgumentException illegalArgumentException) {
                illegalArgumentException.printStackTrace();

            } catch (IllegalAccessException illegalAccessException) {
                illegalAccessException.printStackTrace();

            }
        }

希望这会有所帮助。 快乐学习:)

答案 14 :(得分:0)

通过使用setter方法,您可以在refection的帮助下使用else,您可以通过设置该成员说a - 使用类的私有成员 - 从课堂上拿一个 并设置a.setAccessible(true);

答案 15 :(得分:0)

您可以在代码中使用访问者(getter和setter方法)。

答案 16 :(得分:0)

我们无法直接访问它。但是使用Setter和Getter我们可以访问,

代码是:

class AccessPrivate1 {    

    private int a=10; //private integer    
    private int b=15;    
    int getValueofA()    
    {    
        return this.a;    

    }    

    int getValueofB()    
    {    
        return this.b;    
    }    
}    


public class AccessPrivate{    
    public static void main(String args[])    
    {    
        AccessPrivate1 obj=new AccessPrivate1();    

        System.out.println(obj.getValueofA()); //getting the value of private integer of class AccessPrivate1    

        System.out.println(obj.getValueofB()); //getting the value of private integer of class AccessPrivate1    
    }    
}    

答案 17 :(得分:0)

如何访问子类中的超类私有成员:

  1. 如果您想要包访问,只需将私有字段更改为protected。它允许访问相同的包子类。
  2. 如果您有私有字段,那么只需提供一些访问者方法(getter),您就可以在子类中访问它们。
  3. 您也可以使用内部类,例如

    public class PrivateInnerClassAccess {
    private int value=20;
    
    class InnerClass {
    
    public void accessPrivateFields() {
        System.out.println("Value of private field : " + value);
    }
    
    }
    
    public static void main(String arr[])
    {
        PrivateInnerClassAccess access = new PrivateInnerClassAccess();
        PrivateInnerClassAccess.InnerClass innerClass = access.new InnerClass();
        innerClass.accessPrivateFields();
    
    }
    
    }
    

    4.您也可以使用反射

     public class A {
    private int value;
    public A(int value)
    {
        this.value = value;
    }
    }
    
    public class B {
    public void accessPrivateA()throws Exception
    {
        A a = new A(10);
        Field privateFields = A.class.getDeclaredField("value");
        privateFields.setAccessible(true);
        Integer value = (Integer)privateFields.get(a);
        System.out.println("Value of private field is :"+value);
    }
    
    
    public static void main(String arr[]) throws Exception
    {
        B b = new B();
        b.accessPrivateA();
    }
    }
    

答案 18 :(得分:0)

您无法直接从外部直接访问任何类的私有变量。

您可以使用 getter setter 访问私人会员。

答案 19 :(得分:0)

要访问子类中父类的私有变量,可以使用protected或将getter和setter添加到父类中的私有变量。

答案 20 :(得分:0)

    Class A
{
  private int i;

  int getValue()
    {
      return i;
  }
}
class B extends A
{
   void getvalue2()
    {
      A a1= new A();
      sop(a1.getValue());
    }
}

答案 21 :(得分:0)

显然,让它们受到保护,或添加setter / getter是首选技术。反思是绝望的选择。

只是向面试官展示,如果“访问”意味着读取访问,而IF类A生成XML或JSON等,您可以序列化A并解析有趣的字段。

答案 22 :(得分:0)

私有成员可以在子类中以无法更改变量的方式访问,但您可以以只读方式访问该变量。

答案 23 :(得分:0)

我不了解Java,但在某些语言中 嵌套 类型可以执行此操作:

    class A {
        private string someField;
        class B : A {
            void Foo() {
                someField = "abc";
            }
        }
    }

否则,请使用存取方法或protected字段(尽管它们经常被滥用)。

答案 24 :(得分:0)

私人将被隐藏,直到您获得正确的访问权限。例如编写父母的程序员的Getters或setter。如果它们不可见,那么接受它们只是私有而且无法访问的事实。为什么你要这么做?

答案 25 :(得分:-1)

简单!!!

public class A{
private String a;
private String b;
//getter and setter are here
}

public class B extends A{
public B(String a, String b){ //constructor
super(a,b)//from here you got access with private variable of class A
}
}

感谢

答案 26 :(得分:-1)

请注意,子类可以访问超类的私有字段(例如,如果两个类都是同一个类的成员),那么私有字段永远不会被继承 由子类

答案 27 :(得分:-1)

修饰符是您添加到这些定义以更改其含义的关键字。 Java语言有各种各样的修饰符,包括:

  • Java Access Modifiers
  • 非访问修饰符

要使用修饰符,请在类,方法或变量的定义中包含其关键字。修饰符在语句的其余部分之前。

此处有更多信息:

http://tutorialcorejava.blogspot.in/p/java-modifier-types.html