Мне нужен «Runnable, который принимает параметр», хотя я знаю, что такого runnable на самом деле не существует.
Это может указывать на фундаментальный недостаток в дизайне моего приложения и / или умственный блок в моем усталом мозге, поэтому я надеюсь найти здесь несколько советов о том, как сделать что-то вроде следующего, не нарушая фундаментальные принципы ОО:
private Runnable mOneShotTask = new Runnable(String str) {
public void run(String str) {
someFunc(str);
}
};
Любая идея, как сделать что-то подобное выше?
Consumer<T>
.Consumer<T>
Ответы:
Прошло уже почти 9 лет с тех пор, как я опубликовал это, и, честно говоря, с тех пор Java сделала несколько улучшений. Я оставлю свой оригинальный ответ ниже, но людям не нужно делать то, что в нем. 9 лет назад, во время проверки кода, я бы спросил, почему они это сделали, и, возможно, одобрил, а может и нет. С доступными современными лямбдами, безответственно иметь такой высоко голосованный ответ, рекомендующий устаревший подход (который, честно говоря, был сомнительным для начала ...) В современной Java этот обзор кода был бы немедленно отклонен, и это было бы предложил:
Как и прежде, такие детали, как осмысленная обработка этой темы, оставлены читателю в качестве упражнения. Но, прямо скажем, если вы боитесь использовать лямбды, вам следует еще больше бояться многопоточных систем.
Оригинальный ответ, просто потому что:
Вы можете объявить класс прямо в методе
источник
Вы могли бы поместить это в функцию.
(Когда я использовал это, моим параметром был целочисленный идентификатор, который я использовал для создания хэш-карты ID -> myRunnables. Таким образом, я могу использовать хэш-карту для публикации / удаления различных объектов myRunnable в обработчике.)
источник
Runnable
объект, возвращаемый методом, существует где-либо,paramStr
вероятно, он не будет иметь права на сборку мусора. Возможно, что если объект существует, но никогда не сможет быть запущен снова, JIT (или даже javac) может решить удалить его из области, но мы не должны полагаться на такие оптимизации, потому что они могут измениться в будущем.Создать функцию инициализации, которая возвращает сам объект и инициализировать параметры с ним.
источник
Я использую следующий класс, который реализует интерфейс Runnable . С помощью этого класса вы можете легко создавать новые темы с аргументами
источник
public RunnableArg(Object... args) { setArgs(args); }
затем описывать локальный класс:class ActionArg extends RunnableArg { public ActionArg(Object... arg) { super(arg); } @Override public void run() { /* getArgs() and process them */ } }
и использовать егоThread t = new Thread(new ActionArg( %param_object(s)% )); t.start();
У вас есть два варианта:
Определить именованный класс. Передайте ваш параметр конструктору именованного класса.
Ваш анонимный класс должен быть закрыт по вашему «параметру». Обязательно отметьте это как
final
.источник
Начиная с Java 8, лучший ответ - использовать
Consumer<T>
:https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html
Это один из функциональных интерфейсов, что означает, что вы можете назвать его как лямбда-выражение:
источник
Сначала я хотел бы знать, что вы пытаетесь выполнить, чтобы аргумент передавался в новый Runnable () или run (). Обычным способом должно быть наличие объекта Runnable, который передает данные (str) своим потокам, устанавливая переменные-члены перед запуском. Затем метод run () использует значения переменных-членов для выполнения someFunc ().
источник