我的面试官问我关于内部阶级的问题。向他解释了一切之后,他用我的一句话阻止了我-如果内部阶级可以访问外部阶级的私人成员,那么这是否侵犯了隐私? 我无法回答。
答案 0 :(得分:1)
答案是No
,因为内部类是外部类的一部分,就像其他变量和方法一样
一个类的所有private
变量/方法都可以在同一类的所有方法内访问。内部类是一种特殊情况,其中InnerClass的实例只能存在于OuterClass的实例中。因此,它可以直接访问其封闭实例的方法和字段。
答案 1 :(得分:1)
从JVM的角度来看,是的,内部类访问外部类的私有成员会侵犯隐私。
但是,从Java的角度来看,不,它不侵犯隐私。
Java虚拟机规范第5.4.4. Access Control节说:
只有当以下任何条件为真时,类或接口D才能访问字段或方法R:
[...]
R为
private
,并且在D中声明。
因此,JVM仅允许从同一类中的代码访问private
成员,即嵌套类无法访问外部类的private
成员。
Java语言规范的第6.6.1. Determining Accessibility部分说:
仅当可访问类型并且声明该成员或构造函数允许访问时,才可以访问引用类型的成员(类,接口,字段或方法)或类类型的构造函数。
[...]
否则,将成员或构造函数声明为
private
,并且仅当在顶级类的正文中发生访问时,才允许进行访问。({{3} })包含成员或构造函数的声明。
因此,顶层类和/或嵌套类中的private
成员可以从该顶层类中的代码随时随地访问。由于嵌套类按定义出现在封闭的顶级类的主体内,因此嵌套类中的代码可以访问外部类的private
个成员。
为解决这一差异,Java编译器创建了隐藏(合成)方法,以允许在密切相关的类之间(即,顶级类及其所有嵌套类之间)进行“私有”访问。
这是编译器的内部技巧,在规范中并未真正记录。 JVMS的§7.6部分说:
[...]必须使用
Synthetic
属性来标记未出现在源代码中的类成员,否则必须设置其ACC_SYNTHETIC
标志。 [...]JDK 1.1中引入了
Synthetic
属性,以支持嵌套的类和接口。
有关更多信息,请在网络上搜索4.7.8. The Synthetic Attribute。
答案 2 :(得分:0)
答案:没有内部阶级不会损害外部阶级的隐私。
说明:类中定义的所有实例方法都可以访问该类中定义的私有或非私有字段和方法。这是因为所有实例方法和字段都属于该类的当前对象。 对于任何内部(非静态)类也是如此,它具有对外部类当前对象的隐式引用。 这就是为什么您只能在外部类的对象的帮助下创建内部(非静态)类的对象的原因。如果您在外部类的任何实例方法中创建内部类的对象,则将在外部类的隐式当前对象引用的帮助下创建该对象。
如果您的内部类是静态的,则它没有对外部类当前对象的隐式引用。任何实例字段或方法都属于该类的Object。因此,静态内部类无法访问任何私有或非私有实例字段或外部类的方法。
您可以显式设置外部容器类对象的引用,然后再访问。 现在,借助此显式设置的外部类引用,您可以访问私有的字段和方法。
因此现在让我们将问题修改为为什么带有外部类显式引用的内部静态类可以访问并修改 private 方法和字段?
答案与我们做出此类设计的决定有关。在类的范围内定义任何实体的意图是 belongingness 。如果缺少 belongingness ,则应重新考虑将类设置为内部(静态或非静态)的决策。当我们希望封装实体的子责任时,应该进行内部类的构造。这使得相关责任仍然具有凝聚力。 Iterator是任何Collection的一部分,因此它是内部类。在android的Custom Activity类中定义的Custom AsyncTask类通常被制成私有静态(外部类活动的引用很弱)以防止活动泄漏,因为其目的是修改私有字段。
P.S:Afer编译器编译代码后会为内部类生成单独的文件,您可以参考链接以了解当将其他类定义为内部类时,一个类可被其他类访问的字段之间的交互是如何发生的 https://stackoverflow.com/a/24312109/504133。实际上,合成的getter和setter是由编译器注入代码中的,以便嵌套的静态类可以使用它们访问私有字段。但这仍然是由语言工具完成的后端任务。
答案 3 :(得分:0)
答案为否,因为内部类具有到外部类的内部链接,并且没有外部类的具体实例就不存在内部类。
但是,如果将 static 添加到内部类声明中,则意味着它没有指向外部类的链接,并且在您自己的文件中声明类时,这是相同的。
>仅此而已,简单明了。
答案 4 :(得分:0)
如果仔细查看语句const RadioGroup = props => {
const handleRadioChange = e => {
const currentChecked = parseInt(e.target.value);
props.onRadioChange(currentChecked);
};
return (
<div id={`group-${props.id}`}>
<input
type="radio"
value={0}
checked={props.checkedRadio === 0}
onChange={handleRadioChange}
/>
<label>0</label>
<input
type="radio"
value={1}
checked={props.checkedRadio === 1}
onChange={handleRadioChange}
/>
<label>1</label>
<input
type="radio"
value={2}
checked={props.checkedRadio === 2}
onChange={handleRadioChange}
/>
<label>2</label>
<input
type="radio"
value={3}
checked={props.checkedRadio === 3}
onChange={handleRadioChange}
/>
<label>3</label>
</div>
);
};
和#1
,您会发现它们之间的唯一区别是在#2
中创建的一个(内部类的)额外对象, 请确保所有访问方式完全相同。
没有冲突,因为某处是您故意通过#1
或public
之类的访问说明符打开大门的。内部类不能充当(或不能充当)替代方案,因此绝对不违反。
protected