2015-08-20 3 views
0
public class ClassGenericParameterized<T> { 

    public void add(T t1, T t2){ 
     //System.out.println(t1+t2); 
     System.out.println(Integer.parseInt(t1.toString()) + Integer.parseInt(t2.toString()));   
    } 

    public void multiply(T t1, T t2){ 
     System.out.println(Integer.parseInt(t1.toString()) * Integer.parseInt(t2.toString()));   
    } 

    public void subtract(T t1, T t2){ 
     System.out.println(Integer.parseInt(t1.toString()) - Integer.parseInt(t2.toString()));   
    } 

    public void division(T t1, T t2){ 
     System.out.println(Integer.parseInt(t1.toString())/Integer.parseInt(t2.toString()));   
    } 

    public static void main(String[] args) { 

     ClassGenericParameterized<Integer> ob = new ClassGenericParameterized<Integer>(); 
     ob.add(1,2); 
     ob.multiply(2, 4); 
     ob.subtract(15, 6); 
     ob.division(6, 3); 

    } 
} 

Какова логика и необходимость создания класса Generic в Java
при замене оператораСоздание класса Generic в Java

ClassGenericParameterized<Integer> ob = new ClassGenericParameterized<Integer>() 

по

ClassGenericParameterized<Double> ob = new ClassGenericParameterized<Double>() 

дает

Error(The method add(Double, Double) in the type ClassGenericParameterized<Double> is not applicable for the arguments (int, int)) 

Как мое мышление это из-за заявление, написанное, как внутри метода добавления в Integer.parseInt(t1.toString()) + Integer.parseInt(t2.toString())

так снова попытался заменить заявление

System.out.println(Integer.parseInt(t1.toString()) + Integer.parseInt(t2.toString())); 

по

System.out.println(t1+t2) 

, который дает

Error(The operator + is undefined for the argument type(s) T, T). 

Тогда как это могло быть общим в реальном смысле? Может ли кто-нибудь объяснить, почему это происходит, и как исправить эту ошибку для реализации моей функциональности?

+2

Проблема в том, что 'int' не может быть автобоксирован до' Double'. –

+0

И вы полностью недопонимаете дженерики, так как фактический тип 'T' не имеет смысла внутри ваших методов. – Andreas

+0

Да, что я уже догадался, как его исправить? @sotirios – MAX

ответ

1

В этом случае дженерики не подходят. Причина:

  • Вы не можете просто объявить любой тип, способный сбрасывать, вычитать, умножать или делить. T имеет верхнюю границу Object.

  • Если вы установили привязку к <T extends Number>, это все равно не сработает, поскольку вы не можете гарантировать, что вы можете автоблокировать все, что захотите, в этом параметре, к типу T, к которому был привязан класс.

В конечном счете, вы будете хотеть, чтобы посмотреть на использование Number вместо в качестве параметра. Поскольку Number является родительским классом всех числовых оболочек, включая BigInteger и BigDecimal, вы можете использовать это вместо этого.

public class NumberOperations { 

    public void add(Number t1, Number t2){ 
     //System.out.println(t1+t2); 
     System.out.println(Integer.parseInt(t1.toString()) + Integer.parseInt(t2.toString())); 
    } 

    public void multiply(Number t1, Number t2){ 
     System.out.println(Integer.parseInt(t1.toString()) * Integer.parseInt(t2.toString())); 
    } 

    public void subtract(Number t1, Number t2){ 
     System.out.println(Integer.parseInt(t1.toString()) - Integer.parseInt(t2.toString())); 
    } 

    public void division(Number t1, Number t2){ 
     System.out.println(Integer.parseInt(t1.toString())/Integer.parseInt(t2.toString())); 
    } 

    public static void main(String[] args) { 

     NumberOperations ob = new NumberOperations(); 
     ob.add(1, 2); 
     ob.multiply(2, 4); 
     ob.subtract(15, 6); 
     ob.division(6, 3); 

    } 
} 
0

Немного теории первым:

дженерик в Java (и других языках) представляет собой метод языка ориентированного использовать ту же программу для обработки полностью непересекающиеся типов.

Наиболее распространенным примером являются контейнеры Collection: Любая коллекция хранит объекты типа «любой», которые неизвестны во время компиляции, но всегда будут одинаковыми во время выполнения. Например:

public class MyClass<T> 
{ 
    private T[] array; 
    public void set(T t) {...} 
    public T get() {...} 
    public T[] get2() {...} 
    public Set<T> get3() {...} 
} 

При составлении этого класса, мы не знаем, что будет T. Но с этой клиентской программы:

MyClass<String> obj=new MyClass<String>(); 

...У нас будет объект MyClass, который будет всегда ограничен String: каждое сообщение T будет заполнено String.

Если вы хотите, чтобы какие-то иерархия ограничений в своем родовом классе, вы можете потребовать, чтобы параметр типа имеет минимальный суперкласс так:

public class MyClass<T extends SomeOtherClass> 

Теперь давайте перейдем к практической задаче:

  • Ваша абстракция хорошо спроектирована, но используется неправильно: в методе main вы находитесь под значениями int. Это нормально для параметра Integer, но будьте осторожны: если вы измените параметр Double, вы должны также изменить значения, представленные в качестве входных параметров для методов.

  • Altough хорошо разработана, она не правильно реализована: То, как вы преобразовать значения Т для целых беден: одна программа-клиент может заявить:

    ClassGenericParameterized<String> s=new ClassGenericParameterized<String>(); s.add("hello", "world");

... и компилятор передаст это как ОК, но во время выполнения вы получите NumberFormatException, который не хочет, чтобы вы хотели.

Подумайте об этом: Если вы хотите закодировать абстракцию, которая ориентирована только числовые значения, вы должны полагаться на компилятор, чтобы проверить, что только числовые типы представлены в качестве параметров типа: Сделайте T расширить Number:

public class MyClass<T extends Number> 

... и таким образом вы можете воспользоваться методом intValue(), чтобы преобразовать их в ints. И, самое главное, вам не нужно будет использовать небезопасные методы parse *, которые могут вызывать непредсказуемые исключения во время выполнения.

+0

thankyou @Little Santi, отличное объяснение ... tnx alot – MAX

+0

, но, наконец, мне нужно t1.intValue(), которое опять не применимо для double и т. Д., Что копирует мою родословную класса – MAX

+0

Нет, совсем нет: вы можете законно вызывать 'intValue' в любом подклассе Number: Integer, Double, Long, Float и т. д. И он будет работать нормально. –

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