Основной метод с общим параметром; почему это работает?

public static <T extends String> void main(T[] args) {
    System.out.println("Hello World!");
}

Мне было любопытно узнать, будет ли приведенный выше фрагмент кода компилироваться и запускаться успешно, и это так! Тем не менее, я также задавался вопросом, что произойдет, если T extends String будет заменено на T extends String & AutoClosable; String не реализует AutoClosable, поэтому я не ожидал, что это сработает успешно, но оно все равно работает!

public static <T extends String & AutoCloseable> void main(T[] args) {
    System.out.println("This still works!");
}

Поэтому мой вопрос: почему это все еще успешно работает?

Примечания:

  • Я тестирую это с помощью Java 10.0.1
  • Intellij не играет хорошо с этим методом, потому что он не видит его в качестве точки входа в программу; Я не тестировал его с другими IDE.
  • Вы также можете передавать аргументы с помощью командной строки так же, как и с любой другой программой.

Ответ 1

Это связано с тем, что параметр типа имеет ограничение:

<T extends String>                  =>  String

<T extends String & AutoCloseable>  =>  String & AutoCloseable

И байт-код после стирания тот же, что и для обычной main декларации в обоих случаях:

public static main([Ljava/lang/String;)V

JLS §4.4. Переменные типа:

Порядок типов в привязке имеет значение только в том смысле, что стирание переменной типа определяется первым типом в его привязке и что тип класса или переменная типа может появляться только в первой позиции.