2016-07-04 4 views
2

Я новичок в дженериков и смотрел на этот ответ:преобразованный к типу в Java

https://stackoverflow.com/a/17165079/1632141

Он отлично работает, но я не мог понять, как работает эта часть кода.

public T calories(int val) { 
    calories = val; 
    return (T) this; 
} 

во внутреннем классе NutritionFacts.

Как работает литье? Я ожидал здесь java.lang.ClassCastException, так как мы бросаем чистый объект суперкласса в подкласс.

+1

Что значит «чистый объект суперкласса»? 'this' всегда заканчивается типом' T' в любом случае. –

+0

Код запускается в контексте 'public static class (GMOFacts.) Builder расширяет NutritionFacts.Builder <(GMOFacts.) Builder>'. Поэтому 'T' является собственным типом строителя, который делает его законным. Также 'this' не относится к типу суперкласса, хотя код объявлен в суперклассе. 'this' всегда является конкретным типом времени выполнения (подкласс). – zapl

+1

@LouisWasserman: Неправда. Возможно, что 'this' не будет иметь тип' T'. – newacct

ответ

2

На самом деле есть проблема с этим ответом:

public static class Builder<T extends Builder> {... 

Тип T является сырье типа. Оно должно быть:

public static class Builder<T extends Builder<T>> {... 

, который называется себя ссылающийся типа, потому что это расширение себя.

Обычно используется так:

public class SubBuilder extends Builder<SubBuilder> {... 

в этом случае тип является типом самого подкласса.

Вы можете указать другой подкласс Builder как тип, но это не будет особенно полезно.

+0

Спасибо .. Это помогает .. – starkk92

+0

Я хотел сказать, что 'T' - это тип самого подтипа * – Bohemian

+0

Да. Получите его. Спасибо – starkk92

-1

Вы не бросаете объект суперкласса в подкласс там. Для GMOFacts.Builder объекта, метод calories будет тип стертый к чему-то вроде этого:

public GMOFacts.Builder calories(int val) { 
     calories = val; 
     return (GMOFacts.Builder) this; 
    } 

И this опорные точки для GMOFacts.Builder объекта в любом случае, так что это допустимый тип броска.

+1

Как раз потому, что код стираемого типа действителен, не означает, что общий метод безопасен по типу. – newacct

+0

@newacct Извините, я не понял. Вы говорите об этом конкретном методе или о всех общих методах вообще? Можете ли вы подробно рассказать? –

+1

Как я могу написать метод ' T foo (Object x) {return (T) x; } ', который также будет иметь допустимый при удалении, но явно не безопасен для типов. Тот факт, что стертый код самого метода не содержит бросок, который может терпеть неудачу, не означает, что общий метод безопасен по типу, потому что общий тип возвращаемого типа приводит к тому, что в вызывающий код вставляются отливки и это может потерпеть неудачу. – newacct

Смежные вопросы