Es ist unmöglich, eine solche Kompilierungszeitbeschränkung aufzuerlegen. Generische Typparameter sind Stellvertreter für Referenztypen; Sie unterscheiden nicht zwischen Klassentypen und Schnittstellentypen. Die Tatsache, dass zusätzliche Grenzen in der Deklaration eines Typparameters Schnittstellentypen sein müssen, ist nur nebensächlich - Ihre Strategie, dies als Mittel zur Imputation eines Typs als Schnittstelle zu nutzen, war clever, aber sie unterliegt der Einschränkung, dass die Typparameter can't be used in multiple bounds.
Ihre einzigen Optionen sind für eine Laufzeitprüfung an den Anrufer mit sein mit Class.isInterface()
wie Louis Wasserman pointed out, oder lassen Sie ihn abzurechnen verantwortlich, was es geht in. So oder so, stellen Sie sicher, klar zu dokumentieren, die Erwartungen des Verfahrens und Verhalten.
B
sollte ein Platzhalter für einen Platzhalter sein, so dass der Kunde ein einzelnes Objekt zu bekommen, die sowohl ein SomeClass
und ein A
ist ohne Gießen auf Vertrauen zu tun. Der Kunde muss keinen Zugriff auf den Namen der tatsächlichen Klasse, die
Dies scheint ein Widerspruch zu mir SomeClass
und A
implementiert. Es hat keinen Sinn, B
zu deklarieren, wenn der Aufrufer nicht wissen kann, was er auswertet. Denken Sie daran: Der Aufrufer einer generischen Methode stellt seine Typargumente zur Verfügung. So kann ein Anrufer, der B
entscheidet, ohne etwas, auf dem er basiert, nur raten - und das kann nie typsicher sein.
Es scheint, wie das, was Sie möchten, dass Ihre Methode wirklich zurück eine Art ist, die sowohl eine SomeClass
und ein A
, aber das ist schwierig, weil sie einen gemeinsamen Supertyp nicht teilen:
public static <A> SomeClass&A makeSomeClass(A thing) {...}
(diese ist nonsensical syntax nur für Demonstrationszwecke)
Als Workaround, alternative Möglichkeiten zur Darstellung sowohl eine SomeClass
und einige Schnittstellentyp. Zum Beispiel eine gemeinsame Methode hat ein SomeClass
für die Rückgabe der Kandidaten Schnittstellen könnte:
public interface IsSomeClass {
SomeClass asSomeClass();
}
public interface Foo extends IsSomeClass { }
Die Umsetzung asSomeClass
in der Tat nur this
zurückkehren würde. Dann könnten Sie tun:
public static <A extends IsSomeClass> A makeSomeClass(Class<A> type) {...}
Und der Anrufer dieser Methode wäre in der Lage das zurückgegebene Objekt entweder als Typ zu verwenden:
final Foo foo = makeSomeClass(Foo.class);
final SomeClass someClass = foo.asSomeClass();
Wenn die Schnittstellen selbst kann nicht geändert werden, dann eine andere Option ist stattdessen eine Wrapper-Klasse und Zusammensetzung zu verwenden:
final class SomeClassWrapper<A> {
private final SomeClass someClass;
private final A a;
//constructor and getters, etc.
}
und Ihre Methode stattdessen eine Wrapper-Instanz zurückkehren würde, die Umsetzung Instanz Zuweisen beidesomeClass
und a
:
public static <A> SomeClassWrapper<A> makeSomeClass(Class<A> type) {...}
Nein, ist es nicht möglich. –
Das gibt mir ein trauriges Gesicht :( – torquestomp
Auf der anderen Seite, wenn Sie eine Reflexion getriebene Sache wollen, könnten Sie einfach eine 'Class ' übergeben und 'Class.isInterface()' explizit nennen. –