如何创建一个包含泛型嵌套类实例的数组?

huangapple go评论105阅读模式
英文:

How to create an array of instances of generic nested classes?

问题

我试图创建一个由泛型内部类对象派生的实例数组。

当我这样做时

  1. delivery.columns = new Delivery.Column[] { delivery.new Number (), delivery.new Date () };

我会收到以下警告:

  1. Table.java:58: warning: [rawtypes] found raw type: Table.Column
  2. delivery.columns = new Delivery.Column[] { delivery.new Number (), delivery.new Date () };
  3. ^
  4. missing type arguments for generic class Table.Column<V>
  5. where V is a type-variable:
  6. V extends Object declared in class Table.Column
  7. Table.java:58: warning: [unchecked] unchecked conversion
  8. delivery.columns = new Delivery.Column[] { delivery.new Number (), delivery.new Date () };
  9. ^
  10. required: Table.Column<Object>[]
  11. found: Table.Column[]
  12. 2 warnings

如果我遵循警告中的要求,并执行以下操作:

  1. delivery.columns = new Delivery.Column<Object>[] { delivery.new Number (), delivery.new Date () };

我会得到以下错误:

  1. Table.java:58: error: incompatible types: Delivery.Number cannot be converted to Table.Column<Object>
  2. delivery.columns = new Delivery.Column<Object>[] { delivery.new Number (), delivery.new Date () };
  3. ^
  4. Table.java:58: error: incompatible types: Delivery.Date cannot be converted to Table.Column<Object>
  5. delivery.columns = new Delivery.Column<Object>[] { delivery.new Number (), delivery.new Date () };
  6. ^
  7. Table.java:58: error: generic array creation
  8. delivery.columns = new Delivery.Column<Object>[] { delivery.new Number (), delivery.new Date () };
  9. ^
  10. 3 errors

如何在没有警告和错误的情况下解决此问题?

这是完整的示例代码:

  1. import java.util.stream.Collectors;
  2. import java.util.stream.Stream;
  3. import static java.lang.System.err;
  4. abstract class Table
  5. {
  6. String name = null;
  7. Column<Object>[] columns = null;
  8. abstract class Column<V>
  9. {
  10. String name = null;
  11. Integer type = null;
  12. class Value
  13. {
  14. V value;
  15. Value (V value)
  16. {
  17. this.value = value;
  18. }
  19. }
  20. public String toString ()
  21. {
  22. return name + ": " + type.toString();
  23. }
  24. }
  25. public String toString ()
  26. {
  27. return this.name + " ("
  28. + Stream.of(columns).map (Column<Object>::toString).collect (Collectors.joining (", "))
  29. + ")";
  30. }
  31. }
  32. class Delivery extends Table
  33. {
  34. { name = "Delivery"; }
  35. class Number extends Delivery.Column<String>
  36. {
  37. { name = "Number"; }
  38. }
  39. class Date extends Delivery.Column<String>
  40. {
  41. { name = "Date"; }
  42. }
  43. public static void main (String[] args)
  44. {
  45. String[] strings;
  46. Delivery delivery = new Delivery ();
  47. delivery.columns = new Delivery.Column<Object>[] { delivery.new Number (), delivery.new Date () };
  48. err.println (delivery);
  49. }
  50. }
英文:

I try to create an array of instances of inner class objects, which are derived from generic inner classes.

When I do this

  1. delivery.columns = new Delivery.Column[] { delivery.new Number (), delivery.new Date () };

I get the warnings:

<!-- language: none -->

  1. Table.java:58: warning: [rawtypes] found raw type: Table.Column
  2. delivery.columns = new Delivery.Column[] { delivery.new Number (), delivery.new Date () };
  3. ^
  4. missing type arguments for generic class Table.Column&lt;V&gt;
  5. where V is a type-variable:
  6. V extends Object declared in class Table.Column
  7. Table.java:58: warning: [unchecked] unchecked conversion
  8. delivery.columns = new Delivery.Column[] { delivery.new Number (), delivery.new Date () };
  9. ^
  10. required: Table.Column&lt;Object&gt;[]
  11. found: Table.Column[]
  12. 2 warnings

And if I follow the requirement in the warning and do the following

  1. delivery.columns = new Delivery.Column&lt;Object&gt;[] { delivery.new Number (), delivery.new Date () };

I get the following errors:

<!-- language: none -->

  1. Table.java:58: error: incompatible types: Delivery.Number cannot be converted to Table.Column&lt;Object&gt;
  2. delivery.columns = new Delivery.Column&lt;Object&gt;[] { delivery.new Number (), delivery.new Date () };
  3. ^
  4. Table.java:58: error: incompatible types: Delivery.Date cannot be converted to Table.Column&lt;Object&gt;
  5. delivery.columns = new Delivery.Column&lt;Object&gt;[] { delivery.new Number (), delivery.new Date () };
  6. ^
  7. Table.java:58: error: generic array creation
  8. delivery.columns = new Delivery.Column&lt;Object&gt;[] { delivery.new Number (), delivery.new Date () };
  9. ^
  10. 3 errors

How to solve this problem without warning and error?

This is the complete example:

  1. import java.util.stream.Collectors;
  2. import java.util.stream.Stream;
  3. import static java.lang.System.err;
  4. abstract class Table
  5. {
  6. String name = null;
  7. Column&lt;Object&gt;[] columns = null;
  8. abstract class Column&lt;V&gt;
  9. {
  10. String name = null;
  11. Integer type = null;
  12. class Value
  13. {
  14. V value;
  15. Value (V value)
  16. {
  17. this.value = value;
  18. }
  19. }
  20. public String toString ()
  21. {
  22. return name + &quot;: &quot; + type.toString();
  23. }
  24. }
  25. public String toString ()
  26. {
  27. return this.name + &quot; (&quot;
  28. + Stream.of(columns).map (Column&lt;Object&gt;::toString).collect (Collectors.joining (&quot;, &quot;))
  29. + &quot;)&quot;;
  30. }
  31. }
  32. class Delivery extends Table
  33. {
  34. { name = &quot;Delivery&quot;; }
  35. class Number extends Delivery.Column&lt;String&gt;
  36. {
  37. { name = &quot;Number&quot;; }
  38. }
  39. class Date extends Delivery.Column&lt;String&gt;
  40. {
  41. { name = &quot;Date&quot;; }
  42. }
  43. public static void main (String[] args)
  44. {
  45. String[] strings;
  46. Delivery delivery = new Delivery ();
  47. delivery.columns = new Delivery.Column&lt;Object&gt;[] { delivery.new Number (), delivery.new Date () };
  48. err.println (delivery);
  49. }
  50. }

答案1

得分: 2

以下是翻译好的部分:

我不确定这是否是一个适当的解决方案,更像是使用 List<Column<?>> 容器的一种变通方法(正如 @Andy Turner 在评论中建议的那样)。然后,如果需要,可以将列表转换为列数组。

  1. // 抽象类 Table
  2. protected List<Column<?>> columns;
  3. protected Column<?>[] arrColumns = null;
  4. public Column<?>[] getColumnsAsArray() {
  5. if (null == columns) {
  6. return null;
  7. }
  8. Column<?>[] arr = (Column<?>[]) Array.newInstance(Column.class, columns.size());
  9. return columns.toArray(arr);
  10. }
  11. public String toString() {
  12. return this.name
  13. + "\nlist: (" + columns.stream().map(Column::toString).collect(Collectors.joining(", ")) + ")"
  14. + "\narr: (" + Stream.of(arrColumns).map(Column::toString).collect(Collectors.joining(", ")) + ")";
  15. }

因此,可以创建列的列表,并按如下所示转换为数组:

  1. public class Main {
  2. public static void main(String[] args) {
  3. Delivery delivery = new Delivery();
  4. delivery.columns = Arrays.asList(delivery.new Number(), delivery.new Date());
  5. delivery.arrColumns = delivery.getColumnsAsArray();
  6. err.println(delivery);
  7. Arrays.stream(delivery.arrColumns)
  8. .map(Object::getClass)
  9. .forEach(System.out::println);
  10. }
  11. }
  12. class Delivery extends Table {
  13. { name = "Delivery"; }
  14. class Number extends Table.Column<Number> {
  15. { name = "Number"; type = 1; } // define _type_ to prevent NPE in Column<V>::toString
  16. }
  17. class Date extends Table.Column<String> {
  18. { name = "Date"; type = 10; } // define _type_ to prevent NPE
  19. }
  20. }

输出

  1. # 错误输出
  2. Delivery
  3. list: (Number: 1, Date: 10)
  4. arr: (Number: 1, Date: 10)
  5. # 标准输出
  6. class Delivery$Number
  7. class Delivery$Date

在线演示(已更新)

已使用编译器选项 -Xlint:all 进行验证

英文:

I am not sure if it is a proper solution, it's more like a workaround using a List&lt;Column&lt;?&gt;&gt; container (as @Andy Turner suggested in the comments).
Then the list can be converted into array of columns if needed.

  1. // abstract class Table
  2. protected List&lt;Column&lt;?&gt;&gt; columns;
  3. protected Column&lt;?&gt;[] arrColumns = null;
  4. public Column&lt;?&gt;[] getColumnsAsArray() {
  5. if (null == columns) {
  6. return null;
  7. }
  8. Column&lt;?&gt;[] arr = (Column&lt;?&gt;[]) Array.newInstance(Column.class, columns.size());
  9. return columns.toArray(arr);
  10. }
  11. public String toString() {
  12. return this.name
  13. + &quot;\nlist: (&quot; + columns.stream().map(Column::toString).collect(Collectors.joining(&quot;, &quot;)) + &quot;)&quot;
  14. + &quot;\narr: (&quot; + Stream.of(arrColumns).map(Column::toString).collect(Collectors.joining(&quot;, &quot;)) + &quot;)&quot;;
  15. }

So, the list of columns can be created and converted to array as shown below:

  1. public class Main {
  2. public static void main(String[] args) {
  3. Delivery delivery = new Delivery();
  4. delivery.columns = Arrays.asList(delivery.new Number(), delivery.new Date());
  5. delivery.arrColumns = delivery.getColumnsAsArray();
  6. err.println(delivery);
  7. Arrays.stream(delivery.arrColumns)
  8. .map(Object::getClass)
  9. .forEach(System.out::println);
  10. }
  11. }
  12. class Delivery extends Table {
  13. { name = &quot;Delivery&quot;; }
  14. class Number extends Table.Column&lt;Number&gt; {
  15. { name = &quot;Number&quot;; type = 1; } // define _type_ to prevent NPE in Column&lt;V&gt;::toString
  16. }
  17. class Date extends Table.Column&lt;String&gt; {
  18. { name = &quot;Date&quot;; type = 10; } // define _type_ to prevent NPE
  19. }
  20. }

Output

  1. # stderr
  2. Delivery
  3. list: (Number: 1, Date: 10)
  4. arr: (Number: 1, Date: 10)
  5. # stdout
  6. class Delivery$Number
  7. class Delivery$Date

Online demo (updated)

Verified with compiler option -Xlint:all

huangapple
  • 本文由 发表于 2020年8月26日 17:44:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/63594889.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定