示例:
public class TestClass {
public static void main(String[] args) {
TestClass t = new TestClass();
}
private static void testMethod() {
abstract class TestMethod {
int a;
int b;
int c;
abstract void implementMe();
}
class DummyClass extends TestMethod {
void implementMe() {}
}
DummyClass dummy = new DummyClass();
}
}
我发现上面的代码在Java中是完全法律的的。我有以下问题。
1.在一个方法中定义一个类有什么用呢?
1.是否将为DummyClass
生成类文件
1.我很难想象这种面向对象的概念。在一个行为中有一个类定义。也许有人能用真实的世界中的例子来告诉我。
1.方法中的抽象类听起来有点疯狂。但是不允许接口。这背后有什么原因吗?
8条答案
按热度按时间zpqajqem1#
这称为局部类。
2是简单的一个:是的,将生成一个类文件。
1和3是同一个问题,你可以使用一个局部类,你不需要示例化一个局部类,也不需要知道实现细节,只需要在一个方法中。
一个典型的用法是创建一个接口的一次性实现,例如,你经常会看到这样的东西:
如果您需要创建一组这样的对象并对其执行某些操作,则可以将其更改为
关于接口:我不确定是否有技术问题使得本地定义的接口成为编译器的问题,但即使没有,它们也不会添加任何值。如果实现本地接口的本地类在方法外部使用,则接口将毫无意义。如果本地类只在方法内部使用,则接口和类都将在该方法内部实现。因此接口定义是多余的。
rqqzpn5f2#
这些被称为局部类。你可以找到详细的解释和一个here的例子。这个例子返回一个特定的实现,我们不需要知道方法之外的内容。
omvjsjqw3#
1.类在方法外部是不可见的(例如,示例化,不使用Reflection访问它的方法),而且,它可以访问testMethod()中定义的局部变量,但在类定义之前。
1.我真的以为:“不会写入这样的文件。”直到我刚刚试过:是的,创建了这样一个文件!它的名称类似于A$1B.class,其中A是外部类,B是本地类。
1.特别是对于回调函数(GUI中的事件处理程序,比如当按钮被点击时的onClick()等),使用“匿名类”是很常见的--首先是因为你可能会得到很多这样的类。但是有时匿名类并不够好--特别是你不能在它们上面定义构造函数。在这种情况下,这些方法本地类是一个很好的选择。
6mw9ycah4#
这样做的真实的目的是允许我们在函数调用中创建内联类,以安慰那些喜欢假装自己在用函数式语言编写代码的人;)
edqdpe6u5#
只有在满足以下条件时,您才希望拥有完整的函数内部类与匿名类(也称为Java闭包)
1.需要提供接口或抽象类实现
1.您希望使用在调用函数中定义的一些final参数
1.需要记录接口调用的执行状态。
例如,有人想要一个
Runnable
,而您想要记录执行开始和结束的时间。使用匿名类是不可能做到的,使用内部类可以做到这一点。
这里有一个例子可以证明我的观点
在使用此模式之前,请评估普通的旧顶级类、内部类还是静态内部类是更好的选择。
4bbkushb6#
定义内部类(在一个方法或类中)的主要原因是处理封闭类和方法的成员和变量的可访问性。内部类可以查找私有数据成员并对其进行操作。如果在方法中,它也可以处理最终的局部变量。
拥有内部类确实有助于确保该类不能被外界访问,尤其是在GWT或GXT等的UI编程中,JS生成代码是用java编写的,每个按钮或事件的行为必须通过创建匿名类来定义
f4t66c6m7#
我在Spring中遇到过一个很好的例子,框架在方法内部使用局部类定义的概念,以统一的方式处理各种数据库操作。
假设您有这样的代码:
让我们先看看execute()的实现:
请注意最后一行,Spring对其余的方法也做了同样的“把戏”:
局部类的“技巧”允许框架在一个通过StatementCallback接口接受这些类的方法中处理所有这些场景。这个方法充当了操作(执行、更新)和围绕它们的常见操作(例如执行、连接管理、错误转换和dbms控制台输出)之间的桥梁。
x6h2sr288#
这里的一切都很清楚,但是我想为下一个读者提供另一个合理用例的例子。
关于@jacob-mattison的回答,如果我们假设在接口的这些一次性实现中有一些共同的操作,那么,最好写一次,但也保持实现匿名:
然后,使用这个定义的类并单独实现特定任务就很容易了: