这是我在接受采访时被问到的一个问题:我有A级私人成员,B级扩展A.我知道一个班级的私人成员无法访问,但问题是:我需要访问私人成员B类中的A类,而不是在B类中创建具有相同值的变量。
答案 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 SecurityManager和AccessibleObject。感谢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)
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
的子类Guavapublic 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)
如何访问子类中的超类私有成员:
您也可以使用内部类,例如
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语言有各种各样的修饰符,包括:
要使用修饰符,请在类,方法或变量的定义中包含其关键字。修饰符在语句的其余部分之前。
此处有更多信息:
http://tutorialcorejava.blogspot.in/p/java-modifier-types.html