有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Lambda表达式和非类Java方法

在Java中声明方法时,它们是否需要是类的一部分?我熟悉实用程序类的概念:

实用程序类,也称为帮助程序类,是一个只包含静态方法的类,它是无状态的,不能实例化。它包含一组相关方法,因此可以在整个应用程序中重用

然而,我们可以创建一个完全独立于任何类的方法吗?(我假设范围在默认情况下成为公共的,并且为范围声明任何其他内容都可能导致错误)

如果这是不可能的,也许这可以解释对实用程序类的需求,但我不确定,因为我以前没有考虑过这一点-我自然地认为您可以将函数与任何特定类分离,但我一直在查看各种代码示例,找不到发生这种情况的特定示例

我问这个问题的部分原因是我在回顾这篇文章(并在第2点中提到):

https://www.geeksforgeeks.org/lambda-expressions-java-8/

在其中,它声明:Lambda表达式是在Java8中添加的,并提供以下功能

1)允许将功能视为方法参数,或将代码视为数据

2)可以创建而不属于任何类的函数

3)可以像传递对象一样传递lambda表达式,并根据需要执行


共 (2) 个答案

  1. # 1 楼答案

    Java是一种纯粹基于类的编程语言。所以,是的,它和一切都需要成为一个类的一部分

    您是对的,您可以创建一个实用程序类来生成方法public static,这样就可以在不实例化类的情况下调用方法

    回答评论中的问题:

    Why would someone write Object.method() instead of just method()?

    Object类是java.lang包中的标准类。不应创建名为Object的类,否则需要在使用java.lang.Object的任何地方指定java.lang.Object

    现在你可能是说

    Why would someone write MyUtilClass.method() instead of just method()?

    假设您有一个类MyUtilClass,如下所示

    public class MyUtilClass {
        public static int utilMethodA() {
            return 1;
        }
    
        public static boolean utilMethodB() {
            int value = utilMethodA();
            if(value == 1)
                return true;
            else
                return false;
        }
    }
    

    假设您有另一个类MyClass作为

    public class MyClass {
        public void classMethod() {
          int value =  MyUtilClass.utilMethodA();
        }
    }
    

    这里,如果您在MyUtilClass中看到,utilMethodB()使用utilMethodA()而不写MyUtilClass.utilMethodA()(但是,我们也可以这样写)。在这里,我们不需要将它写为MyUtilClass.utilMethodA(),因为编译器可以在不完全指定它的类的情况下找到utilMethodA(),因为它存在于它自己的类中

    现在,在MyclassmyMethod()中,我们必须指定MyUtilClass.utilMethodA()(没有它,它将无法工作),因为编译器无法确定您是想调用MyUtilClassutilMethodA()。可能有数百个类具有名为utilMethodA()的方法,但编译器无法找出要调用的一百个方法中的哪一个

    注意:-

    另外,您可以像这样执行static import{}

    import static my.package.name.MyUtilClass.myMethodA()
    

    然后在MyClass内使用utilMethodA()而不加前缀MyUtilClass(但是您已经通过静态导入通知compile您将使用utilMethodA()of MyUtilClass对吗?)

    你觉得很酷吗?不 这是一种相当糟糕的方式,因为

    • 它使代码看起来不明显。在一个大班里,似乎 方法utilMethodA()是在 MyClass
    • 此外,如果对utilMethodA()进行了多个静态导入,它还可以向编译器生成歧义。因为编译器无法确定您打算使用这两个选项中的哪一个

    (编辑)关于Lambda表达式

    Lambda表达式是Java8中添加的非常酷的东西。它们基本上是一种功能。它们为您提供了在需要使用它们的地方定义函数的能力。例如,在这个link that you provided中,请参见下面显示的示例syntax of lambda,其中包含语句

     ArrayList<Integer> arrL = new ArrayList<Integer>(); 
            arrL.add(1); 
            arrL.add(2); 
            arrL.add(3); 
            arrL.add(4); 
    arrL.forEach(n -> { if (n%2 == 0) System.out.println(n); });
    

    基本上,我们在这里做的是,我们定义一个函数,如果n是2的倍数,我们打印n。我们在做arrLforEach元素。您看到了吗,我们定义了要在函数调用forEach()中的每个元素上执行的函数。这就是lambda表达的美妙之处

    现在,说到你的问题

    So the primary benefit of lambda (besides syntax) is to make it easier to implement functional interfaces (compared to what alternative)?

    是的,有点。简单来说,不需要创建单独的类来实现接口,然后实现抽象方法,然后调用实现的方法

    这需要大量的工作,特别是如果您只需要调用该方法一次,例如

    考虑功能界面{{CD36}},定义在您的问题中的链接:

    interface FuncInterface {
        // An abstract function
        void abstractFun(int x);
    
        // A non-abstract (or default) function
        default void normalFun() {
            System.out.println("Hello");
        }
    }
    

    现在,您的功能接口需要两种实现:

    • 两次提供所传递的int x的一种
    • 另一个提供通过的int x平方

    因此,您对其进行了两种实现:

    第一FuncInterfaceTwiceImpl

    public class FuncInferFaceTwiceImpl implements FuncInterface {
        @Override
        public void abstractFun(int x) {
            System.out.println(2 * x);
        }
    }
    

    第二,作为

    public class FuncInterfaceSquareImpl implements FuncInterface {
        @Override
        public void abstractFun(int x) {
            System.out.println(x * x);
        }
    }
    

    现在,你称他们为

    public class MyClass {
    
        public static void main(String[] args) {
            FuncInterface interfaceTwiceObject = new FuncInferFaceTwiceImpl();
            interfaceTwiceObject.abstractFun(5);
            FuncInterface interfaceSquareObject = new FuncInterfaceSquareImpl();
            interfaceSquareObject.abstractFun(5);
        }
    }
    

    它打印

    10
    25
    

    现在,你要做什么

    • 您必须创建两个单独的(在单独的新文件或 可以在MyClass的同一文件中创建私有类, 每个都实现了抽象方法
    • 然后实例化每个类的对象并调用它们 分别在main函数中

    如果这是最重要的呢唯一一个你不得不称之为twicesquare的地方?您必须创建两个类才能只使用一次。这种努力太多了

    • 如果您不想在类中创建新类和实现方法的情况下调用它呢
    • 如果我告诉您只提供方法体,我将为您完成这项工作,而无需您费心实现接口和重写方法,该怎么办

    兰姆达魔法来了。而不是仅仅创建任何impl

    • 直奔主方法
    • 实例化FuncInterface的两个对象,在Lambda表达式中只提供方法体
    • 从对象调用抽象方法,如下所示
    public class MyClass {
    
        public static void main(String[] args) {
            FuncInterface interfaceTwiceObject = (n) -> System.out.println(2*n);
            interfaceTwiceObject.abstractFun(5);
            FuncInterface interfaceSquareObject = (n) -> System.out.println(n*n);
            interfaceSquareObject.abstractFun(5);
        }
    }
    

    和繁荣,输出是

    10
    25
    

    又一次是Lambda救了你一天

  2. # 2 楼答案

    是的,Java中的所有方法都必须是类的一部分。不能创建与类不关联的方法(静态或其他)


    编辑

    在回答您的问题之前,我将指出lambda表达式是通过SAM types的概念在Java8中引入的。此外,还引入了一些语法上的修饰,以便于创建这些类型

    当您在Java中听到术语“Lambda表达式”时,您应该始终记住它们是表达式。您的困惑源于认为lambda表达式计算为与类或对象无关的纯函数;这在Java中根本不是这样,我将向您说明原因

    Lambda表达式不是函数

    我现在知道你的困惑是从哪里来的了,因为你正在读的那篇文章提出了一个错误的说法,他们说,lambda表达式是

    A function that can be created without belonging to any class.

    这根本不是事实。Java中的lambda表达式不是函数。以他们给出的例子为例

    interface FuncInterface 
    { 
        // An abstract function 
        void abstractFun(int x); 
    
        // A non-abstract (or default) function 
        default void normalFun() 
        { 
           System.out.println("Hello"); 
        } 
    }
    
    class Test 
    { 
        public static void main(String args[]) 
        { 
            // lambda expression to implement above 
            // functional interface. This interface 
            // by default implements abstractFun() 
            FuncInterface fobj = (int x)->System.out.println(2*x); 
    
            // This calls above lambda expression and prints 10. 
            fobj.abstractFun(5); 
        } 
    } 
    

    证明

    现在看看他们在main方法中的评论:

    lambda expression to implement above functional interface

    从一开始,他们就承认下一行代码实现了一个功能接口。但是Java中的函数不实现接口,只有类或其他接口可以实现

    现在,他们甚至继续“调用”这个函数:

    This calls above lambda expression and prints 10.

    除了不直接调用函数(如果这真的是一个函数,任何人都会这样做),他们使用属性访问器符号(.)来访问他们想要调用的实际方法,这意味着我们这里的不是一个函数,而是一个匿名类的实例

    此外,由于这个对象实际上包含另一个方法(normalFun),人们可能会问这样一个问题,当我想将这个“函数”传递给另一个方法时,我应该使用哪个方法在lambda函数的上下文中,这不是一个常见的问题(如果有的话),因为lambda函数只有一件事要做,那就是调用它

    在结束时

    Java有lambda表达式,而不是lambda函数

    使它成为lambda表达式的原因仅仅是Java8中引入的语法糖,它使用了() -> { }符号。不幸的是,许多函数式编程的爱好者开始将术语“Lambda函数”与使用此语法创建的对象相关联,这导致了您在问题中表达的混淆

    为了重申我之前的回答,Java中的所有函数都是类的一部分,您不能拥有与对象无关的函数,也不能在类之外创建函数