2010-01-10 3 views
3

Как написать общий метод в Java.Как написать общий метод в Java

В C# я хотел бы сделать это

public static T Resolve<T>() 
    { 
     return (T) new object(); 
    } 

Что эквивалент в Java?

+5

Ваш код C# вызывает InvalidCastException, если 'T' не является' объектом'. – dtb

+0

ваш общий метод C# не является хорошим примером, так как для почти любого значения T, которое бросает бросок. –

ответ

11

Во-первых, ваш пример C# неверен; он будет бросать InvalidCastException, если только typeof(T) == typeof(object). Вы можете это исправить, добавив constraint:

public static T Resolve<T>() where T : new() { 
    return new T(); 
} 

Теперь, это было бы равнозначно синтаксис в Java (или, по крайней мере, так близко, как мы можем получить):

public static <T> T Resolve() { 
    return (T) new T(); 
} 

Обратите внимание на двойной упоминание о T в декларации: один - это T в <T>, который параметризует метод, а второй - тип возврата T.

К сожалению, приведенное выше не работает на Java. Из-за того, как внедрены генерические средства Java, информация о времени выполнения около T недоступна, и поэтому приведенное выше дает ошибку времени компиляции. Теперь, вы можете обойти это ограничение, так как:

public static <T> T Resolve(Class<T> c) { 
    return c.newInstance(); 
} 

Обратите внимание на необходимость принятия в T.class. Это называется runtime type token. Это идиоматический способ справиться с этой ситуацией.

+0

Это будет исключать некоторые исключения! Не используйте отражение в этих случаях. –

+0

@tackline: Нет, это идиоматическая Java для обработки этой ситуации: ср. http://java.sun.com/docs/books/tutorial/extra/generics/literals.html – jason

+0

«Во-первых, ваш пример C# неверен». Я не думаю, что для метода было исключено исключение в определенных ситуациях (пример OP) (особенно в вопросе о синтаксисе). Однако я считаю, что метод не компилируется (ваш пример C#). Вы забыли '' после 'Resolve'. –

1

Попробуйте http://java.sun.com/docs/books/tutorial/extra/generics/methods.html

public static <T> T Resolve() 
    { 
     return (T) new Object(); 
    } 

Будьте осторожны (T), но я не уверен, что это правильно. Я знаю, что общий ролик вызывает множество проблем. Я уже провел с ним много времени ...

+2

Не будет ли этот код бросить 'java.lang.ClassCastException'? – missingfaktor

+0

Это нормально работает в Java, потому что T во время компиляции стирается до Object. Однако вы действительно не получаете никакой безопасности типов от этой реализации. –

+0

@ GreyMatter 9: Правильно, метод Resolve вызывает java.lang.ClassCastException, если T - любой другой тип, кроме java.lang.Object. –

2

Как и другие комментаторы отметили, вы можете сделать это с помощью Java, а также - с такой большой возможности создать исключение произнесения во время выполнения:

@SuppressWarnings("unchecked") 
public static <T> T resolve() { 
    return (T) new Object(); 
} 

Если вы не используете @SuppressWarnings аннотацию, однако, Java тип erasure вступает в игру, и вы получите предупреждение о компиляторе. Исключение будет также происходить где-то еще: если вы пытаетесь его использовать:

String s = <String>resolve(); 

будет исключать.

С другой стороны, вы, вероятно, хотели бы использовать new T() в C#. Это невозможно сделать на Java. Предлагаемое обходное решение заключается в использовании Class<T> в качестве параметра типа, если вам нужно полагаться на информацию о типе во время выполнения.Для примера, это будет означать, что вы должны реорганизовать его в этой версии:

public static <T> T resolve(Class<T> type) { 
    try { 
    return type.newInstance(); 
    } catch(Exception e) { 
    // deal with the exceptions that can happen if 
    // the type doesn't have a public default constructor 
    // (something you could write as where T : new() in C#) 
    } 
} 

Кстати, вы можете использовать это также, чтобы избавиться от предупреждения в предыдущем случае, и поместить исключение во время выполнения в более чувствительная линия:

public static <T> T resolve(Class<T> type) { 
    return type.cast(new Object()); 
} 

Этот фрагмент кода будет вести себя так же, как тот, который вы дали в качестве примера - в том числе исключение, которое происходит, когда T любого типа отличается от Object.

0

Вы хотите какой-то фабрики:

public interface MyFactory<T> { 
    T newInstance(); 
} 

Затем, которые могут быть переданы в где это необходимо. В вашем коде:

public static T resolve<T>(MyFactory<T> factory) { 
    return factory.newInstance(); 
} 

Примечание: нет абсолютно никаких оснований для использования отражения для этого !!

+0

Как новый текст написан внутри MyFactory . Неужели для создания нового экземпляра необходимо использовать отражение? (Извините, переход с C# на Java по-прежнему). – Lisa

+0

Scratch этот вопрос. Я вижу, что тип класса java (java.lang.Class) имеет метод newInstance() для генерации нового экземпляра, где есть конструктор без параметров. – Lisa

+0

@Lisa Вы действительно не хотите, чтобы прикоснуться к отражению, если вы можете помочь. Реализации 'MyFactory' могут построить определенный' T' по своему усмотрению. –

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