简体   繁体   English

新列表<A & ? extends B>();</a>

[英]new List<A & ? extends B>();

If you know how to run the title line, just scroll down to tl;dr or write an answer! 如果您知道如何运行标题行,只需向下滚动到tl; dr或写一个答案!

I wrote the rest of the text to avoid the XY problem . 我写了其余的文章以避免XY问题 It doesn't matter anymore, when this is done. 完成后,这不再重要。


Context 上下文

I want to create an object that takes a generic (List, Map, whatever). 我想创建一个使用通用对象(列表,地图等)的对象。

The objects within the list should fullfill 2 criterias: 列表中的对象应满足2个条件:

  1. having mymethod() (which I realized from creating an Interface having this as a method head) 具有mymethod() (我通过创建一个以该方法作为方法头的接口来实现)
  2. Extending JComponent 扩展JComponent

How I tried to make this work: 我如何使这项工作:

  1. I created multiple classes, any of these are implementing MyInterface and are extending a JComponent (subclasses of it). 我创建了多个类,其中任何一个都实现了MyInterface并扩展了JComponent(它的子类)。 That's where I run in my title problem: new List<MyInterface extends JComponent); 那就是我出现标题问题的地方: new List<MyInterface extends JComponent);
  2. Another idea: creating an abstract class (that fits all criteria) instead of an Interface. 另一个想法:创建一个抽象类(适合所有​​标准)而不是一个接口。 Problem: The concrete classes I need do not extend the same class. 问题:我需要的具体课程不会扩展同一课程。
  3. I thought of Generics, just like: public abstract class MyClass<X extends JComponent> extends X , but this can't work – for obvious reasons. 我想到了泛型,就像: public abstract class MyClass<X extends JComponent> extends X ,但这是行不通的-出于明显的原因。 (eg I have to implement the abstract methods from a superclass, but if it's a Generic I cannot know by now.) (例如,我必须从超类实现抽象方法,但是如果我现在不知道它是泛型的话)。

tl;dr TL;博士

I run in a problem which could easily be made if you can make this line working: 我遇到了一个问题,如果可以使此行正常工作,那么很容易做到:

new List<A extends B>();

or, introduced by @khelwood: new List(); 或由@khelwood引入:new List();

where: 哪里:

  • A is an Interface (just as I could declare a new List<MyInterface>() A是一个接口(就像我可以声明一个new List<MyInterface>()
  • and any item extends ? extends B 和任何项目扩展? extends B ? extends B (example: it can be a JTextField or a JTextArea or whatever they like, but it has to be a (subclass of) JComponent (JComponent = B)) ? extends B (示例:它可以是JTextField或JTextArea或任何他们喜欢的东西, 但它必须是JComponent (的子类) (JComponent = B))

If you want to be able to create a list of things which extend JComponent and implement your interface, and add things to such a list, you need to define a concrete type which implements both: 如果您希望能够创建扩展JComponent并实现您的接口的事物的列表,并将事物添加到此类列表中,则需要定义一个具体的类型,该类型同时实现这两种:

List<ThatType> list = new ArrayList<>();
list.add(new ThatType());

You can declare a type variable for this, in order to write a generic method: 您可以为此声明一个类型变量,以便编写一个通用方法:

<T extends JComponent & YourInterface> void something(T thing) {
  // ...
}

<Something extends SomethingElse> only works in the declarations of type variables. <Something extends SomethingElse>仅适用于类型变量的声明。

Moreover, you don't create a list of Somethings that extends SomethingElse : you create a list of Somethings , and whether or not Something extends SomethingElse depends upon how those types are defined. 此外,您不会创建Somethings that extends SomethingElse列表:您会创建Somethings列表,并且Somethings是否Something extends SomethingElse取决于如何定义这些类型。

To make this more concrete, you don't make a new List<String extends Object> : you make a List<String> , and String happens to extend Object . 为了更具体一点,您不需要创建new List<String extends Object> :创建List<String> ,而String恰好是Object扩展。

You need to declare the type variables appropriately, eg: 您需要适当地声明类型变量,例如:

class Foo<B> {
  <A extends B> List<A> list() {
    return new List<>();
  }
}

You say that: 你说:

Another idea: creating an abstract class (that fits all criteria) instead of an Interface. 另一个想法:创建一个抽象类(适合所有​​标准)而不是一个接口。 Problem: The concrete classes I need do not extend the same class. 问题:我需要的具体课程不会扩展同一课程。

but at the same time you say that they extend JComponent . 但同时您说它们扩展了JComponent The only possibility for this to occur is that they all transitively extend JComponent . 发生这种情况的唯一可能性是它们都可传递地扩展了JComponent So at some point up the inheritance hierarchy there is a direct inheritance from JComponent . 因此,在继承层次结构的某个点上,存在来自JComponent的直接继承。

If this is still your code, this is the point where you could introduce another class, instead of a JComponent that extends JComponent and implements your interface. 如果这仍然是你的代码,这是你可以介绍的,而不是另一个类,点JComponent扩展JComponent和实现你的接口。

If not then I think it could be impossible to achieve using only syntax. 如果不是这样,我认为仅使用语法是不可能实现的。

I don't think the type system allows you to do exactly what you want and get compile-time type safety. 我认为类型系统不能让您完全按照自己的意愿做,并获得编译时的类型安全。

One approximation is the following: 一种近似如下:

List<JComponent> componentList = new ArrayList<>();
List<MyInterface> myInterfaceList = (List) componentList;

If you don't mind the compile-time warning, you now have two views on the same list: one shows the content as JComponent 's and the other as MyInterface 's. 如果您不介意编译时警告,则现在在同一列表上有两个视图:一个显示内容为JComponent ,另一个显示为MyInterface

You can add the objects to either view and then read them from the view that provides the right type for the context. 您可以将对象添加到任一视图中,然后从为上下文提供正确类型的视图中读取它们。

Naturally, when you add an object the compiler will not check that the inserted object subclasses both JComponent and MyInterface . 自然地,当您添加对象时,编译器将不会检查插入的对象是否同时MyInterfaceJComponentMyInterface子类。 That is your responsibility. 那是你的责任。

If you want more (run-time) type safety, you can go this way: 如果您想要更多(运行时)类型的安全性,可以采用以下方式:

List rawList = new ArrayList();
List checkedList = Collections.checkedList(rawList, JComponent.class);
List doublyCheckedList = Collections.checkedList(checkedList, MyInterface.class);
List<JComponent> componentList = doublyCheckedList;
List<MyInterface> myInterfaceList = doublyCheckedList;

If you only insert into doublyCheckedList , at runtime the list will check that the inserted objects subclass both JComponent and MyInterface . 如果仅插入doublyCheckedList ,则在运行时列表将检查插入的对象是否同时MyInterfaceJComponentMyInterface When reading, you can use the two views as in my previous fragment. 阅读时,您可以像我之前的片段中一样使用这两种视图。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 带通配符的泛型(地图 <? extends A, List<? extends B> &gt;) - Generics with Wildcards (Map<? extends A, List<? extends B>>) java从List转换<B>为List <A>,其中B扩展为A.</a> - java cast from List<B> to List<A> where B extends A <A><B>当B扩展A时,</a>从列表转换<A>为列表</a> - Cast from List<A> to List<B> when B extends A 当B扩展A时,为什么B b = new A()无效而A a = new B()有效? - Why B b = new A() is invalid and A a = new B() is valid when B extends A? 如果B扩展了A,则不能将List强制转换<A>为List <B>(很有意义),但是为什么一个可以将List强制转换</a> <? extends A> <A><B>列出<B>?</a> - If B extends A, one cannot cast List<A> to List<B> (makes sense), but then why can one cast List<? extends A> to List<B>? 在列表上使用addAll() <? extends E> a和b不起作用 - Using addAll() on List<? extends E> a and b doesn't work 添加(列表<!--? extends Z--> ) 其中 Z 是一个接口。 Class B 扩展 A 实现 Z 为什么我们不能用 List 调用 add()<a></a> - add (List<? extends Z>) where Z is an interface . Class B extends A implements Z why cant we call add() with a List<A> 列表<?>列表 = 新的 ArrayList<String> (); 列表<? extends Object>列表 = 新的 ArrayList<String> (); - List<?> list = new ArrayList<String>(); List<? extends Object> list = new ArrayList<String>(); 名单 <? extends Object> #add(new MyClass())无法编译 - List<? extends Object>#add(new MyClass()) doesn't compile A <T extends B>和A <?有什么区别?延伸B>? - What is the difference between A<T extends B> and A<? extends B>?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM