简体   繁体   English

通用构造函数在Java中的作用是什么?

[英]What purpose do generic constructors serve in Java?

As everyone knows you can have a generic class in Java by using type arguments: 众所周知,通过使用类型参数,您可以在Java中使用泛型类:

class Foo<T> {
    T tee;
    Foo(T tee) {
        this.tee = tee;
    }
}

But you can also have generic constructors , meaning constructors that explicitly receive their own generic type arguments, for example: 但是您也可以使用泛型构造函数 ,这意味着构造函数显式接收它们自己的泛型类型参数,例如:

class Bar {
    <U> Bar(U you) {
        // Why!?
    }
}

I'm struggling to understand the use case. 我很难理解用例。 What does this feature let me do? 这个功能让我做了什么?

The use case I'm thinking of might be that some wants an Object which inherits from 2 Types. 我正在考虑的用例可能是某些人想要一个继承自2种类型的Object。 Eg implements 2 interfaces : 例如实现2个interfaces

public class Foo {

    public <T extends Bar & Baz> Foo(T barAndBaz){
        barAndBaz.barMethod();
        barAndBaz.bazMethod();
    }
}

Though I have never used it in production. 虽然我从未在生产中使用它。

It's clear in the example you provided that U does not play any role in the class' constructor, as it effectively becomes an Object at runtime: 在你提供的示例中很清楚U在类的构造函数中没有扮演任何角色,因为它在运行时实际上变成了一个Object

class Bar {
    <U> Bar(U you) {
        // Why!?
    }
}

But let's say that I wanted my constructor to only accept types that extend some other class or interface, as seen below: 但是,让我们说我希望我的构造函数只接受扩展其他类或接口的类型,如下所示:

class Foo<T extends Baz> {
    <U extends Bar> Foo(U u) {
        // I must be a Bar!
    }
}

Notice that the class already has a different generic type in use; 请注意,该类已经使用了不同的泛型类型; this allows you to utilize a separate, unrelated generic type to the class definition. 这允许您对类定义使用单独的,不相关的泛型类型。

Granted, I've never used something like this, and I've never seen it in use, but it's possible! 当然,我从来没有使用过这样的东西,我从未见过它,但它有可能!

What does this feature let me do? 这个功能让我做了什么?

There are at least three two things it lets you do that you could not otherwise do: 它至少有件让你做的事情,否则你无法做到:

  1. express relationships between the types of the arguments, for example: 表达参数类型之间的关系,例如:

     class Bar { <T> Bar(T object, Class<T> type) { // 'type' must represent a class to which 'object' is assignable, // albeit not necessarily 'object''s exact class. // ... } } 
  2. <withdrawn> <抽出>

  3. As @Lino observed first, it lets you express that arguments must be compatible with a combination of two or more unrelated types (which can make sense when all but at most one are interface types). 正如@Lino首先观察到的那样,它允许你表达参数必须与两个或更多不相关类型的组合兼容(当所有但最多只有一个是接口类型时才有意义)。 See Lino's answer for an example. 请参阅Lino的答案。

Actually, this constructor 实际上,这个构造函数

class Bar {
    <U> Bar(U you) {
        // Why!?
    }
}

is just like a generic method . 就像一个通用的方法 It would make a lot more sense if you had multiple constructor arguments like this: 如果你有这样的多个构造函数参数会更有意义:

class Bar {
    <U> Bar(U you, List<U> me) {
        // Why!?
    }
} 

Then you could enforce the constraint, that they have the same time with the compiler. 然后,您可以强制执行约束,它们与编译器具有相同的时间。 Without making U a generic for the whole class. 不使U成为全班的通用。

Because that unbound generic type erases to Object , it'd be the same as passing Object in your constructor: 因为未绑定的泛型类型会擦除到Object ,所以它与在构造函数中传递Object相同:

public class Foo {
    Object o;

    public Foo(Object o) {
        this.o = o;
    }
}

...but like passing a blank Object , unless you're doing something clever , this has little practical value. ......但是就像传递一个空白Object ,除非你做得很聪明 ,否则这没什么实际价值。

You see benefits and wins if you pass in bound generics instead, meaning that you can actually have guarantees around the type that you care about. 如果您传入绑定泛型,您会看到好处并获胜,这意味着您实际上可以保证您关注的类型。

public class Foo<T extends Collection<?>> {
    T collection;
    public Foo(T collection) {
        this.collection = collection;
    }
}

Effectively, this is more about flexibility than it being something revolutionary. 实际上,这更多的是灵活性,而不是革命性的东西。 If you want the flexibility to pass in a specific category of types, then you have the power to do so here. 如果您希望灵活地传递特定类别的类型,那么您可以在此处执行此操作。 If you don't , then there's nothing wrong with standard classes. 如果你不这样做 ,那么标准类就没有错。 It's merely here for your convenience, and since type erasure is still a thing, an unbound generic is the same (and has the same utility) as passing Object . 它仅仅是为了您的方便,因为类型擦除仍然是一个东西,未绑定的泛型与传递Object是相同的(并具有相同的实用程序)。

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

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