简体   繁体   English

可选单值或集合的Java泛型

[英]Java generics for optional single value or collection

I'm trying to define a container for a whole bunch of classes as some parts of the code will make more sense with a collection but other places will make sense with single values. 我正在尝试为整个类定义一个容器,因为代码的某些部分对集合更有意义,而其他地方对单个值才有意义。

Ideally I'd like to do this: 理想情况下,我想这样做:

public class AllModes<T> {
   private T<Car> car;
   private T<Boat> boat;
   private T<Train> train;
   private T<Plane> plane;
   ...40 more of these...
}

then I'd like to use the class like: 然后我想使用类似的类:

AllModes<List> allModes;
AllModes<Optional> oneOfEachMode;

But I get the error I get is "The type T is not generic; it cannot be parameterized with arguments " 但是我得到的错误是“类型T不是通用的;不能使用参数对其进行参数化”

The reason I'm defining these in multiple variables and not a single HashSet based on a superclass is I want to have get methods that return the correct types to avoid consumers of this class needing to cast down everywhere as each object has its own distinct fields. 我要在多个变量中而不是在基于超类的单个HashSet中定义它们的原因是,我希望有返回正确类型的get方法,以避免此类的使用者需要在任何地方进行转换,因为每个对象都有自己的不同字段。

I also considered just storing a single value list or set but I thought it might less error prone to use the correct type I intended (ie. one value) 我还考虑过仅存储单个值列表或集合,但我认为使用我想要的正确类型(即一个值)可​​能会减少出错的可能性

You can't solve it this way. 您无法通过这种方式解决。 Use the instanceof operator instead. 改用instanceof运算符。 Here is an example: 这是一个例子:

public class AllModes<T> {
    private T object;

    private void check(T object) {
        if(object instanceof Boat){
            System.out.println("Boat");
            // your code for Boat goes here
        } else if (object instanceof Car) {
            System.out.println("Car");
            // your code for Car goes here
        }
    }
}

From The Java™ Tutorials - Why Use Generics? 来自Java™教程-为什么使用泛型? :

By using generics, programmers can implement generic algorithms that work on collections of different types, can be customized, and are type safe and easier to read. 通过使用泛型,程序员可以实现对不同类型的集合工作的泛型算法,可以对其进行自定义,并且类型安全且易于阅读。

You can have multiple types in class and then you can associated them with the fields. 您可以在类中具有多种类型,然后可以将它们与字段关联。 But in your case, you have several fields with some type. 但是在您的情况下,您有几个具有某些类型的字段。 A class don't have much dependencies on others. 一个类对其他人没有太多依赖。 You should design you class in a way that there are no much dependencies there. 您应该以没有太多依赖关系的方式设计类。

public class AllModes<T,T1,T2,T3> {
       private T car;
       private T1 boat;
       private T2 train;
       private T3 plane;

}

You can't achieve what you want using the Java type system. 使用Java类型系统无法实现所需的功能。 Since you can't have a generic container type, you'll need to enforce the invariants with dedicated constructors (or subclasses). 由于您不能具有通用的容器类型,因此需要使用专用的构造函数(或子类)强制执行不变式。

But if you do so, the clients of your class will not be able to distinguish between different container types ( Optional vs List ), they will need to work with a generic abstraction (like Stream , Iterator , Iterable , whatever suits you). 但是,如果这样做,您的类的客户端将无法区分不同的容器类型( OptionalList ),他们将需要使用通用抽象(如StreamIteratorIterable ,任何适合您的容器)。

Here's an example: 这是一个例子:

public class AllModes {
    private final Supplier<Stream<Car>> cars;
    private final Supplier<Stream<Boat>> boats;

    public AllModes(Optional<Car> car, Optional<Boat> boat) {
        // Assuming Java 8, when Optional did not have a stream() method yet
        this.cars = () -> car.map(Stream::of).orElse(Stream.empty());
        this.boats = () -> boat.map(Stream::of).orElse(Stream.empty());
    }

    public AllModes(List<Car> cars, List<Boat> boats) {
        this.cars = cars::stream;
        this.boats = boats::stream;
    }

    public Stream<Car> getCars() {
        return cars.get();
    }

    public Stream<Boat> getBoats() {
        return boats.get();
    }
}

I'd suggest you take a step back and re-consider what exactly you want to achieve with this container. 我建议您退后一步,重新考虑使用此容器要实现的目标。 Eg ask yourself what its domain is or what the client is supposed to do with Allmodes<T> ... 例如,问问自己它的域是什么,或者客户端应该使用Allmodes<T>做什么...

Another more concrete question that comes to mind is how exactly you intend to popuplate that Optional<T> generically? 想到的另一个更具体的问题是,您打算如何精确地泛泛显示Optional<T> Will it be the first element in the List<T> or the last? 它是List<T>的第一个元素还是最后一个? Or an element which satisfies a specific Predicate<T> ? 还是满足特定Predicate<T>的元素?

Your design doesn't seem to be that well thought out yet. 您的设计似乎还没有经过深思熟虑。

What you could do which would come close to what you descibed (in case I got that right) is provide an accessor of type Stream<T> as you could get both a List<T> aswell as an Optional<T> from it. 您可以做的将接近您所描述的(如果我正确的话)的是提供Stream<T>类型的访问器,因为您可以从中获取List<T>Optional<T> Your client would then have to make that decision and also determine how exactly to derive the Optional<T> from the Stream<T> . 然后,您的客户将不得不做出决定,并确定如何精确地从Stream<T>派生Optional<T> Stream<T>

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM