这可能是不可能的,但我试图创建一个只有共享超类的类才能访问的构造函数,几乎是protected修饰符的反向逻辑。我假设没有修改器直接完成这个,但知道我想要完成什么,有什么建议吗?
public Account extends SomeEntity {
//default public
public Account() {
}
// I am wanting this constructor to be only available to sibling classes.
// (those that share the same super class )
<modifier> Account(Element accountElement) {
}
}
public Accounts extends SomeEntity {
private List<Account> accountList;
//default public
public Accounts() {
Account newAcct = new Account(element);
//looped loading up Generic list of Account
this.accountList.add(newAcct);
}
我正在使用RESTful Web服务并使用XML响应构建对象,问题是如果我GET
帐户列表,将其构建到帐户对象列表中我将不得不查询Web为每个个人账户提供服务,即使我已经掌握了这些信息,这看起来效率也很低。
BUT
我不想让我正在构建的API的一般用户能够以这种方式实例化帐户对象。 (使用Element
)
答案 0 :(得分:3)
没有像这样的语言结构。 Package(= default)access是镇上唯一的Java机制,截至1.6。
我确信你可以用堆栈做些讨厌的事情,但我不推荐它们。
答案 1 :(得分:1)
我看看工厂模式。您可以使用工厂方法的访问修饰符来玩游戏,以获得接近您想要的东西。您也可以在工厂方法中使用反射来获得更接近您想要的东西,而不是使用包访问。
答案 2 :(得分:1)
很抱歉,但我仍然不明白这个设计。如果将一个方法添加到一个类中,它的实现可能只会将私有数据用于此类,因此不能保证“兄弟”类可以为这些数据提供这些数据。换句话说,如果您的愿望被授予,您如何保证构造函数Account(Object arg0)实现不会将私有数据用于Account类? (因此对于Accounts类是不可见的)
在我看来,您希望您的代码为单个帐户和帐户列表提供相同的界面 - 扩展SomeEntity类。使用复合图案可以更优雅地完成。
http://en.wikipedia.org/wiki/Composite_pattern
如果您的意图是提供只有子类将使用的自定义构造函数,为什么不在SomeEntity中声明自定义构造函数并使该类抽象?
另外,请记住你可以这样做:
public Account() {
this(new arg0());
}
Account(Object arg0) {
}
不确定这是否有帮助。
答案 3 :(得分:1)
有一种方法可以模拟C ++的朋友功能,从而达到您想要的效果。
警告:这是一种人为的技术,只有在没有其他解决方案的情况下才能使用!
由于在这种情况下没有修改器可以执行您想要的操作,因此诀窍是将访问限制移动到应用修改器的其他位置。为此,请将键参数添加到构造函数中。该密钥是一个只能由允许的“兄弟”类实例化的类,即由给定类的子类实例化。
因此,限制被移动到公共超类,通过常用的修饰符可以限制键的创建。
以下是一个例子:
public class CommonSuperClass {
public static final class Key {
private Key() {}
}
// This is the only way to create a key, and it's protected
protected final Key createKey() {
return new Key();
}
}
public class Account {
// The restricted constructor can even be public
public Account(Key key) {
// Everybody can try with null, but we're not that stupid
// Of course any RuntimeException can be thrown instead
if (key == null) throw new UnsupportedOperationException();
}
}
public class AllowedSibling extends CommonSuperClass {
public void foo() {
// I'm allowed
new Account(this.createKey());
}
}
public class DeniedClass {
public void foo() {
// This doesn't compile
new Account(new Key());
// This will throw an exception
new Account(null);
}
}
答案 4 :(得分:0)
这是一个非常奇怪的必要条件,我认为没有访问修饰符可以做你想要的。无论如何,我建议你只需将构造函数公开并将其记录为“仅供内部使用”。
如果确实需要限制访问权限,您可以使用这个冗长的解决方案:
public class Base {
protected interface Factory {
Base getInstance(Element e);
}
private static Map<Class<?>, Factory> registry = new HashMap<Class<?>, Factory>();
protected static void register(Class<?> c, Factory f) { registry.put(c, f); }
protected static <T extends Base> T create(Class<T> c, Element e) {
return (T) registry.get(c).getInstance(e);
}
}
public class Derived1 extends Base {
protected Derived1(Element e) { }
private static class Derived1Factory implements Factory {
public Derived1 getInstance(Element e) {
return new Derived1(e);
}
}
static {
register(Derived1.class, new Derived1Factory());
}
}
public class Derived2 extends Base {
protected Derived2(Element e) { }
private static class Derived2Factory implements Factory {
public Derived2 getInstance(Element e) {
return new Derived2(e);
}
}
static {
register(Derived2.class, new Derived2Factory());
}
public void method() {
Element e = null;
...
// Put some element in e
...
// This is what you were trying to do
Derived1 d1 = create(Derived1.class, e);
}
}
答案 5 :(得分:0)
public class SomeEntity
protected void init(Element accountElement) {}
public class Account extends SomeEntity
public Account()
....
protected void init(Element accountElement)
....
public class Accounts extends SomeEntity
Account newAcct = new Account();
newAcct.init(element);
答案 6 :(得分:-1)
这是我想尝试的(我没有测试过这种方法):
<modifier> Account(Object arg) {
if (!super.getClass().isAssignableFrom(this.getClass())) {
throw new AssertionError("This constructor is only available to super classes.");
} else {
// Continue...
}
}