了解构造函数的有界泛型参数

时间:2018-08-10 06:50:54

标签: java generics

我很困惑,为什么第一个代码段无法编译,而第二个代码段却没有编译?

我假设在两种情况下,通用参数T描述了相同的可能类型集,因此它们是等效的。

第一个示例

public class Main {

    static Function<B, Integer> f = (b) -> 1;

    Main() {
        this(f);
    }

    <T extends A> Main(Function<T, Integer> f) {

    }

}

class A {    }

class B extends A {    }

第二个示例:

public class Main<T extends A> {

    static Function<B, Integer> f = (b) -> 1;

    Main() {
        this(f);
    }

    Main(Function<T, Integer> f) {

    }

}

class A {    }

class B extends A {    }

产生错误:

  

The constructor Main <T>(Function<B,Integer>) is undefined

3 个答案:

答案 0 :(得分:3)

在第二个示例中,在类级别引入类型参数T,但是始终将使用类B传递固定函数。如果用Main«A»实例化Main怎么办?您的代码类型不安全。

在您的第一个示例中,这不是问题,因为函数的type参数仅在每次调用时确定。

答案 1 :(得分:3)

在第一个代码中,{ "name": "my-testapp", "version": "0.0.0", "license": "MIT", "scripts": { "ng": "ng", "start": "ng serve --base-href /mytestapp/", "build": "ng build", "build-stage": "ng build --environment=stage --aot --prod --vendor-chunk=false --common-chunk=false", "build-prod": "ng build --environment=prod --aot --prod --vendor-chunk=false --common-chunk=false", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, "private": true, "dependencies": { "@angular/animations": "^4.2.4", "@angular/common": "^4.2.4", "@angular/compiler": "^4.2.4", "@angular/core": "^4.2.4", "@angular/forms": "^4.2.4", "@angular/http": "^4.2.4", "@angular/platform-browser": "^4.2.4", "@angular/platform-browser-dynamic": "^4.2.4", "@angular/router": "^4.2.4", "@ngx-translate/core": "^7.2.2", "@ngx-translate/http-loader": "^1.1.0", "bootstrap": "^3.3.7", "core-js": "^2.4.1", "jquery": "^3.2.1", "qrcode": "^1.0.0", "rxjs": "^5.4.2", "zone.js": "^0.8.14" }, "devDependencies": { "@angular/cli": "1.4.2", "@angular/compiler-cli": "^4.2.4", "@angular/language-service": "^4.2.4", "@types/jasmine": "~2.5.53", "@types/jasminewd2": "~2.0.2", "@types/node": "~6.0.60", "codelyzer": "~3.1.1", "jasmine-core": "~2.6.2", "jasmine-spec-reporter": "~4.1.0", "karma": "~1.7.0", "karma-chrome-launcher": "~2.1.1", "karma-cli": "~1.0.1", "karma-coverage-istanbul-reporter": "^1.2.1", "karma-jasmine": "~1.1.0", "karma-jasmine-html-reporter": "^0.2.2", "protractor": "~5.1.2", "ts-node": "~3.2.0", "tslint": "~5.3.2", "typescript": "~2.3.3" } } 参数的作用域为方法:

T

它使用目标的推断(客户端声明的类型返回)来确定<T extends A> Main(Function<T, Integer> f) { } 的值。
因此,只有在T的第一种类型是FunctionA的子类时才可以编译,以遵守A约束。
例如,声明其他这些类:

<T extends A>

这些也将起作用:

class B extends A {    }

class C extends A {    }

class D extends B {    }

在第二个代码中,您要将一个static Function<B, Integer> fb = (b) -> 1; static Function<C, Integer> fc = (b) -> 1; static Function<D, Integer> fd = (b) -> 1; 声明的变量传递给依赖于该类的Function<B, Integer>泛型类型的Main构造函数:

T

问题在于,根据类的客​​户端使用的通用类型,此处的public class Main<T extends A> { Main(Function<T, Integer> f) { } } 可能是TAB的任何其他子类。 br />  因此A无法分配给Function<B, Integer>,并且编译失败。

答案 2 :(得分:0)

这些例子不一样。

示例1-只有构造函数#2是通用的,而构造函数#1和类不是通用的。

因此,编译器仅需在构造#1中推断构造2的参数类型。那很好并且可能。

示例2-整个类都是通用的。 因此,已经针对建筑#1的编译器使用类型.psqlrc。现在,它检查对构造2的调用。结果表明T extends A不等于T extends AB可以是扩展T的任何其他类)。

要澄清-对于泛型类,类型推断(泛型类型的解析)不能在构造函数中发生。它发生在从外部调用构造函数的地方。里面已经完全按照定义给出了。

与该示例相比,仅使用方法(构造函数)类型推断,这可以在构造#1中完美实现。