জাভা 8 লম্বা শূন্য যুক্তি


187

আসুন ধরা যাক জাভা 8 এ আমার নীচের কার্যকরী ইন্টারফেস রয়েছে:

interface Action<T, U> {
   U execute(T t);
}

এবং কিছু ক্ষেত্রে আমার পক্ষে তর্ক বা রিটার্নের ধরণের ছাড়াই একটি ক্রিয়া প্রয়োজন। সুতরাং আমি এই জাতীয় কিছু লিখুন:

Action<Void, Void> a = () -> { System.out.println("Do nothing!"); };

যাইহোক, এটি আমাকে সংকলন ত্রুটি দেয়, আমার এটি লিখতে হবে

Action<Void, Void> a = (Void v) -> { System.out.println("Do nothing!"); return null;};

যা কুৎসিত। Voidটাইপ প্যারামিটার থেকে মুক্তি পাওয়ার কোনও উপায় আছে কি ?


1
একটি সময়ে দেখে নিন stackoverflow.com/questions/14319787/...
BobTheBuilder

7
আপনার যেমন একটি ক্রিয়া প্রয়োজন, যেমন আপনি এটি সংজ্ঞায়িত করেছেন, এটি সম্ভব নয়। যাইহোক, আপনার প্রথম উদাহরণটি কোনওটিতে খাপ RunnableRunnable r = () -> System.out.println("Do nothing!");
অ্যালেক্সিস সি

1
@ BobTheBuilder আমি সেই পোস্টে প্রস্তাবিত কোনও গ্রাহক ব্যবহার করতে চাই না।
উইকু

2
ম্যাট এর উত্তর ধরণের কাজ করে, কিন্তু কলটি যখন নাল ফেরতের মান পায় তখন কী করবে?
স্টুয়ার্ট

8
আপনি আঙ্গুলগুলি অতিক্রম করতে পারেন এবং আশা করতে পারেন যে এই পোস্টের 2 এবং 3 পরামর্শ জাভা 9 এর জন্য গৃহীত হবে!
assylias

উত্তর:


110

আপনি যে সিনট্যাক্সটি পরে রয়েছেন এটি একটি সামান্য সহায়ক ফাংশন দিয়ে সম্ভব যা একটিকে রূপান্তর Runnableকরে Action<Void, Void>(আপনি Actionউদাহরণস্বরূপ এটিকে এটিতে রাখতে পারেন ):

public static Action<Void, Void> action(Runnable runnable) {
    return (v) -> {
        runnable.run();
        return null;
    };
}

// Somewhere else in your code
 Action<Void, Void> action = action(() -> System.out.println("foo"));

4
এটি আপনিই পেতে পারেন যে সবচেয়ে পরিষ্কার কাজ, আইএমও, সুতরাং +1 (অথবা ইন্টারফেসে একটি স্ট্যাটিক পদ্ধতি সহ)
অ্যালেক্সিস সি

কনস্ট্যান্টিন ইয়ভকভের নীচের সমাধানটি (@ ফাংশনাল ইনটারফেস সহ) একটি ভাল সমাধান, কারণ এতে জেনেরিকদের জড়িত না এবং অতিরিক্ত কোডের প্রয়োজন হয় না।
uthomas

@ বুথোমাস দুঃখিত, আমি জড়িত কোনও উত্তর দেখতে পাচ্ছি না @FunctionalInterface। তিনি কেবল বলেছেন, এটি বাড়ানো সম্ভব নয় ...
ম্যাট

1
হাই @ ম্যাট, দুঃখিত। আমি খুব দ্রুত প্রতিক্রিয়া। প্রদত্ত প্রশ্নের জন্য আপনার উত্তরটি পুরোপুরি বৈধ। দুর্ভাগ্যক্রমে, আমার ভোটটি লক হয়ে গেছে, সুতরাং আমি এই উত্তরটি আমার -1 অপসারণ করতে পারি না। দুটি নোট: 1. Runnableঅ্যাকশনের পরিবর্তে কাস্টম @FunctionalInterfaceনামক কিছু গ্রহণ করা উচিত SideEffect, ২. এই জাতীয় সহায়ক ফাংশনটির প্রয়োজনীয়তা হাইলাইট করে যে অদ্ভুত কিছু চলছে এবং সম্ভবত বিমূর্তিটি নষ্ট হয়ে গেছে।
uthomas

528

Supplierএটি কিছু না নেয় তবে ব্যবহার করুন , তবে কিছু ফেরত দেয়।

Consumerএটি কিছু নেয় তবে ব্যবহার করুন , কিন্তু কিছুই ফেরায় না।

Callableযদি এটি কোনও ফলাফল দেয় এবং ফেলতে পারে তবে ব্যবহার করুন ( Thunkসাধারণ সিএসের শর্তে সর্বাধিক অনুরূপ )।

Runnableএটি না করে এবং নিক্ষেপ করতে না পারলে ব্যবহার করুন ।


উদাহরণস্বরূপ আমি এই মোড়ানো "অকার্যকর" রিটার্ন আহবান করেছিলেন, public static void wrapCall(Runnable r) { r.run(); }। ধন্যবাদ
ম্যাক্সেন্স

13
সুন্দর উত্তর। সংক্ষিপ্ত এবং সুনির্দিষ্ট
ক্লিন্ট ইস্টউড

দুর্ভাগ্যক্রমে, এটি অবশ্যই একটি চেক করা ব্যতিক্রম ছুঁড়ে ফেললে সহায়তা করে না।
জেসি গ্লিক

12
এই উত্তরের সমাপ্তি হিসাবে, যা সম্পাদনা করার মতো হবে না: আপনি বায়কনসুমার (2 গ্রহণ করেন, 0 টি রিটার্ন নেন), ফাংশন (1 গ্রহণ করে, 1 রিটার্ন લેবে) এবং বায়ু ফাংশন (2 নেবে, 1 ফেরত নেবে) ব্যবহার করতে পারেন। সেগুলি জানা সবচেয়ে গুরুত্বপূর্ণ
ক্লোভিস

2
কলযোগ্য (এমন কি তার কল () পদ্ধতিতে একটি ব্যতিক্রম ছুঁড়েছে) এর মতো কিছু আছে তবে কি কোনও ফেরতের মান প্রয়োজন?
dpelisek

40

ল্যাম্বদা:

() -> { System.out.println("Do nothing!"); };

আসলে একটি ইন্টারফেসের মতো বাস্তবায়নের প্রতিনিধিত্ব করে:

public interface Something {
    void action();
}

যা আপনি সংজ্ঞায়িত করেছেন তার চেয়ে সম্পূর্ণ আলাদা। এজন্য আপনি একটি ত্রুটি পান।

যেহেতু আপনি আপনার প্রসারিত করতে পারবেন না @FunctionalInterface, বা একেবারে নতুন প্রবর্তন করতে পারবেন না , তাই আমি মনে করি আপনার কাছে খুব বেশি বিকল্প নেই। আপনি Optional<T>ইন্টারফেসগুলি ব্যবহার করে ব্যবহার করতে পারেন যে কিছু মান (রিটার্ন টাইপ বা পদ্ধতি পরামিতি) অনুপস্থিত রয়েছে। যাইহোক, এটি ল্যাম্বডা শরীরটিকে সহজ করে তুলবে না।


সমস্যাটি হ'ল আপনার Somethingফাংশনটি আমার Actionধরণের একটি উপ- টাইপ হতে পারে না এবং আমার দুটি ভিন্ন ধরণের থাকতে পারে না।
উইকু

টেকনিক্যালি তিনি পারবেন, তবে তিনি এড়াতে চান বলে জানিয়েছেন wants :)
কনস্ট্যান্টিন যোভকভ

31

আপনি এই বিশেষ ক্ষেত্রে একটি উপ-ইন্টারফেস তৈরি করতে পারেন:

interface Command extends Action<Void, Void> {
  default Void execute(Void v) {
    execute();
    return null;
  }
  void execute();
}

এটি উত্তরাধিকারসূত্রে প্রাপ্ত প্যারামিটারাইজড পদ্ধতিটিকে ওভাররাইড করতে একটি ডিফল্ট পদ্ধতি ব্যবহার Void execute(Void)করে, কলটিকে সহজ পদ্ধতিতে প্রেরণ করে void execute()

ফলাফলটি এটি ব্যবহার করা অনেক সহজ:

Command c = () -> System.out.println("Do nothing!");

এই অ্যাকশন <শূন্য, অকার্যকর> কোথা থেকে আসছে? সুইং বা জ্যাকস-ডাব্লুএক্স এক্স অ্যাকশন ইন্টারফেসের কোনও যেমন জেনেরিক ইন্টারফেস নেই?
luis.espinal

1
@ luis.espinal: Action<T, U>প্রশ্নে ঘোষণা করা হয়েছে .....
জর্দো

হাহাহাহ, হেক আমি কীভাবে মিস করেছি? ধন্যবাদ!
luis.espinal

5

সেটা সম্ভব না. একটি ফাংশন যা একটি অ-শূন্য রিটার্ন টাইপ (এমনকি এটি হলেও Void) একটি মান ফেরত দিতে হবে। তবে আপনি স্থিতিশীল পদ্ধতিগুলি যুক্ত করতে পারেন Actionযা আপনাকে "তৈরি" করতে দেয় Action:

interface Action<T, U> {
   U execute(T t);

   public static Action<Void, Void> create(Runnable r) {
       return (t) -> {r.run(); return null;};
   }

   public static <T, U> Action<T, U> create(Action<T, U> action) {
       return action;
   } 
}

এটি আপনাকে নিম্নলিখিত লেখার অনুমতি দেবে:

// create action from Runnable
Action.create(()-> System.out.println("Hello World")).execute(null);
// create normal action
System.out.println(Action.create((Integer i) -> "number: " + i).execute(100));

5

আমি মনে করি এই টেবিলটি সংক্ষিপ্ত এবং দরকারী:

Supplier       ()    -> x
Consumer       x     -> ()
Callable       ()    -> x throws ex
Runnable       ()    -> ()
Function       x     -> y
BiFunction     x,y   -> z
Predicate      x     -> boolean
UnaryOperator  x1    -> x2
BinaryOperator x1,x2 -> x3

অন্যান্য উত্তরে যেমন বলা হয়েছে, এই সমস্যার উপযুক্ত বিকল্প হ'ল ক Runnable


4

আপনার কার্যকরী ইন্টারফেসের ভিতরে একটি স্থিতিশীল পদ্ধতি যুক্ত করুন

package example;

interface Action<T, U> {
       U execute(T t);
       static  Action<Void,Void> invoke(Runnable runnable){
           return (v) -> {
               runnable.run();
                return null;
            };         
       }
    }

public class Lambda {


    public static void main(String[] args) {

        Action<Void, Void> a = Action.invoke(() -> System.out.println("Do nothing!"));
        Void t = null;
        a.execute(t);
    }

}

আউটপুট

Do nothing!

3

এটি সম্ভব বলে আমি মনে করি না, কারণ ফাংশন সংজ্ঞা আপনার উদাহরণে মেলে না।

আপনার ল্যাম্বদা এক্সপ্রেশন ঠিক হিসাবে মূল্যায়ন করা হয়

void action() { }

আপনার ঘোষণার মত দেখাচ্ছে

Void action(Void v) {
    //must return Void type.
}

উদাহরণস্বরূপ, যদি আপনার নিম্নলিখিত ইন্টারফেস থাকে

public interface VoidInterface {
    public Void action(Void v);
}

একমাত্র ধরণের ফাংশন (তাত্ক্ষণিক সময়) যা দেখতে তুলনামূলকভাবে দেখাবে

new VoidInterface() {
    public Void action(Void v) {
        //do something
        return v;
    }
}

এবং হয় রিটার্নের বিবৃতি বা যুক্তির অভাব আপনাকে একটি সংকলক ত্রুটি দেবে।

অতএব, আপনি যদি এমন কোনও ফাংশন ঘোষণা করেন যা আর্গুমেন্ট গ্রহণ করে এবং একটিটি ফেরত দেয় তবে আমি মনে করি যে এটি ফাংশনে রূপান্তর করা অসম্ভব যা উপরে বর্ণিত দুটিও নয় neither


3

কেবলমাত্র রেফারেন্সের জন্য কোন কার্যকরী ইন্টারফেসটি পদ্ধতি রেফারেন্সের জন্য ক্ষেত্রে পদ্ধতি নিক্ষেপ করে এবং / অথবা কোনও মান দেয়।

void notReturnsNotThrows() {};
void notReturnsThrows() throws Exception {}
String returnsNotThrows() { return ""; }
String returnsThrows() throws Exception { return ""; }

{
    Runnable r1 = this::notReturnsNotThrows; //ok
    Runnable r2 = this::notReturnsThrows; //error
    Runnable r3 = this::returnsNotThrows; //ok
    Runnable r4 = this::returnsThrows; //error

    Callable c1 = this::notReturnsNotThrows; //error
    Callable c2 = this::notReturnsThrows; //error
    Callable c3 = this::returnsNotThrows; //ok
    Callable c4 = this::returnsThrows; //ok

}


interface VoidCallableExtendsCallable extends Callable<Void> {
    @Override
    Void call() throws Exception;
}

interface VoidCallable {
    void call() throws Exception;
}

{
    VoidCallableExtendsCallable vcec1 = this::notReturnsNotThrows; //error
    VoidCallableExtendsCallable vcec2 = this::notReturnsThrows; //error
    VoidCallableExtendsCallable vcec3 = this::returnsNotThrows; //error
    VoidCallableExtendsCallable vcec4 = this::returnsThrows; //error

    VoidCallable vc1 = this::notReturnsNotThrows; //ok
    VoidCallable vc2 = this::notReturnsThrows; //ok
    VoidCallable vc3 = this::returnsNotThrows; //ok
    VoidCallable vc4 = this::returnsThrows; //ok
}

দয়া করে আরও কিছু প্রসঙ্গ যুক্ত করুন। এটি আকর্ষণীয় দেখায় তবে এর অর্থ অবিলম্বে সুস্পষ্ট নয়।
বিনিল্যান্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.