[英]Private class as return type from public method
为什么这个有效?
Foo.java
public class Foo {
public Bar getBar() {
return new Bar();
}
private class Bar {}
}
如果Bar是私有的,那么这个类的用户将如何使用此方法? 当然可以使用多态,但这不应该是无效的,并且声明应该指出这是返回一个对象吗?
我刚刚对此进行了一些研究,但未能找到明确的答案。 它似乎很可能只是Java语言设计者的疏忽,因为它实际上并没有造成任何伤害。 将public
方法放入private
类并没有什么不同。 即使没有办法实际访问该public
方法,也没有什么能阻止你这样做。
当然,当您尝试执行此操作时,NetBeans会向您发出警告“通过公共API导出非公共类型”。 我希望大多数其他环境会发出类似的警告。
返回的对象对尝试使用它的人来说完全没用(除非他们使用反射),他们几乎所能做的就是将它存储到一个Object
(或者他们有权访问的任何其他超类)中,然后传递该Object
周围。
如果传递的Object
被用作传递但从未操作过的“句柄”,您可能希望这样做。 在这种情况下,尽管将类public
但将其中的所有方法设置为private
以防止它们在类外部执行(或定义返回的public
接口并使private
类实现该方法)仍然更有意义。
所以答案似乎是:
它可能不应该有效,但因为它没有造成任何伤害,它从未被阻止过。
对于类似的主题,这里有一个很好的答案:
为什么这个有效?
因为调用位置中的客户端代码可能期望一个Object
(或根本不期望任何东西),所以从任何地方调用此方法都没有问题:
Object o = new Foo().getBar();
public class Foo {
private String myString;
public String getMyString() {
return myString;
}
}
这也是有效的。 内部类为什么表现不同?
使Bar
private
只会让外部世界看不到,就像将字段设为private
。
一个重要的警告是,即使您能够在Foo
对象上调用getBar()
,也无法调用该引用的方法(因为可见性)。
所以主要的是你可以这样做,但你不应该这样做。
我能想象的唯一情况是当Foo
也是一个内部类而Foo
的外部类想要使用Bar
。
它是有效的,因为Bar
对Foo
类是可见的。 因此它编译。
当然另一个类看不到Bar
,因此不能使用返回值。
但是另一个类仍然可以在不使用返回值的情况下调用该方法。
public class FooBar {
public void invokeBar() {
Foo foo = new Foo();
foo.getBar();
}
}
返回私有类的公共方法可能很有用,您需要能够从任何范围调用该方法(例如,改变Foo的内部状态),如果除了简单调用之外还需要任何类型的结果,还可以用于内部用法方法。
内心阶级
内部类表示一种特殊类型的关系,它可以访问外部类的所有成员(数据成员和方法),包括私有。 嵌套类可以使代码更具可读性和可维护性,因为它仅在一个地方对逻辑上的类进行分组。
它是嵌套类型的一种形式。 这种类声明称为内部类。 如果将内部类声明为static,那么它将被称为顶级嵌套类。 Java中可用的其他形式的嵌套类型是本地类; 在块中声明和定义的类,即方法或构造函数或初始化块。 嵌套类型的第四种形式是匿名类; 没有任何名称的类,其对象用于定义类的位置。
就您的情况而言,即内部类,可以使用public,private和protected访问说明符声明类中的所有类。 封闭类中的所有类以及封闭类本身都共享信任关系。 这意味着,内部类的所有私有成员以及封闭类的私有成员彼此共享。 但是,如果没有封闭类的对象,则无法访问内部类的对象。
当您尝试创建内部类编译器的对象时,将报告编译时错误。 但是下面的示例访问每个其他类的私有成员,即封闭类访问内部类的私有成员和内部类访问封闭类的私有成员:
class Bar {
private static int x;
public void getFoo() {
System.out.println(new Foo().y);
}
private class Foo {
private int y;
public void getBar() {
System.out.println(Bar.x);
}
}
}
public class Test{
public static void main(String[] a) {
Bar b = new Bar();
//Bar.Foo f = new Bar.Foo(); This is completely illegal syntax.
}
}
内部类的最佳示例是包含类的Accounts
类与作为内部类的Transaction
类的关系。 一个Accounts
类可以有多个Transaction
对象,但没有Accounts
对象,Transaction对象不能存在。
尽管如此,返回私有内部类的对象是无用的,因为它在类之外变得不可见。 正如上面的Accounts
和Transaction
类的例子所解释的那样。 没有Accounts
对象, Transaction
不能存在。
我有一个完全有效的用例,我很高兴这是允许的。
让我们留下一个创建UI片段的课程。 它接受一些域对象并创建一个UI:
public Node createPersonUI(Person person) {
BasePanel panel = new BasePanel();
// ... setup panel with values ...
return panel;
}
BasePanel
是Node
的子类,是调用者没有业务的内部类,因为这个类决定了事物的外观。
现在,当我需要支持一个包含更多信息的新对象PersonalProfile
时,我发现自己需要重新使用这个类的一部分,但是还包含基本的Person
数据:
public Node createPersonalProfileUI(PersonalProfile profile) {
BasePanel panel = new BasePanel();
// ... setup panel with values ...
return panel;
}
但是,该代码部分重复,所以我做了:
public Node createPersonalProfileUI(PersonalProfile profile) {
BasePanel panel = (BasePanel)createPerson(profile.getPerson());
// ... only setup missing values ...
return panel;
}
然而,演员BasePanel
有点荒谬 - 将其更改为返回BasePanel
不仅有效,而且不会暴露我的私人类的任何功能。 相反,它只从它继承的任何公共类中公开方法......非常棒!
完整代码:
public BasePanel createPersonUI(Person person) {
BasePanel panel = new BasePanel();
// ... setup panel with values ...
return panel;
}
public BasePanel createPersonalProfileUI(PersonalProfile profile) {
BasePanel panel = createPerson(profile.getPerson());
// ... only setup missing values ...
return panel;
}
private class BasePanel extends Node {
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.