Java: как работает этот код (тип возвращаемого значения не определен) - PullRequest
3 голосов
/ 27 января 2010

В расширенном руководстве по RMI от Sun у них есть некоторый интересный код, который реализует «механизм вычислений», используя RMI, они передают функцию в механизм вычислений, который затем возвращает результаты. Подробнее здесь: http://java.sun.com/docs/books/tutorial/rmi/designing.html

Это означает, что вначале тип возврата неизвестен, поэтому они используют следующий обходной путь:

package compute;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Compute extends Remote {
    <T> T executeTask(Task<T> t) throws RemoteException;
}

и пакет вычислений;

public interface Task<T> {
    T execute();
}

как это может работать? какое свойство java реализует? что я мог прочитать об этом больше?

спасибо!

Ответы [ 5 ]

2 голосов
/ 27 января 2010

Это с использованием Generics. Вы можете прочитать больше здесь http://java.sun.com/developer/technicalArticles/J2SE/generics/

Более конкретно, копирование по ссылке выше

"Здесь T представляет тип элементов, содержащихся в коллекции. Думайте о T как о заполнителе, который будет заменен конкретным типом"

2 голосов
/ 27 января 2010

как работает этот код (тип возвращаемого значения не определен)

В этом коде используется универсальных , а T называется параметром универсального типа . Тип возвращаемого значения не является «неопределенным». Вместо этого мы говорим, что параметризован : тип возвращаемого значения в конечном итоге будет заменен на реальный, конкретный тип. То есть тип возвращаемого значения определяется любым типом Task<T>, который вы создали.

Вы можете думать об этом как о функции, которая принимает определенный тип и генерирует специализированную версию каждого Task<T>, который запрашивается. (Это не совсем то, что происходит под прикрытием - на самом деле, в конечном счете, компилятор отбрасывает информацию о типе времени выполнения универсального объекта - но более углубленная обработка, вероятно, выходит за рамки этого ответа StackOverflow.)

Под прикрытием, когда вы компилируете этот код, компилятор Java позаботится о том, чтобы не нарушалось никаких правил создания Task<T> и отношения к его execute() методам. Например, компилятор пометит это как недопустимое:

public class Boat { ... }
public class Car { ... }

public CarFactory implements Task<Car> {
  public Boat execute() { ... } // Error! A Boat is not a Car.
}
2 голосов
/ 27 января 2010

Это известно как Generics Java .

Чтобы углубиться в подробности, FAQ Анджелики Лангер отлично

0 голосов
/ 27 января 2010

Помимо обобщений, здесь работает еще одна концепция: загрузчик удаленных классов, предоставляемый Java RMI.

Если в «движке вычислений» включена удаленная загрузка классов (для этого требуется SecurityManager, чтобы клиент не запускал вредоносную задачу), он может загружать новые классы во время выполнения с клиента.

0 голосов
/ 27 января 2010

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

Object executeTask(Task<Object> t){...}
Integer executeTask(Task<Integer> t){...}

и т.д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...