我有一个如下定义的示例类:
public class FooBar {
void method1(Foo foo){ // Should be overwritten
...
}
}
后来,当我尝试这个:
FooBar fooBar = new FooBar(){
public String name = null;
@Override
void method1(Foo foo){
...
}
};
fooBar.name = "Test";
我收到一个错误,说明名称字段不存在。为什么?
因为变量"fooBar"
的类型是FooBar
(所述变量中对象的运行时类型是实现FooBar
的匿名类的运行时类型,FooBar
也是FooBar
的子类型)...
...和"fooBar"
类型没有所述成员。因此,编译错误。 (请记住,变量FooBar
可以包含任何符合name
的对象,即使没有Local Class Declaration的对象,因此编译器会拒绝非类型安全的代码。)
编辑:对于一个解决方案,请参阅irreputable的答案,该答案使用(new foobar(){
public String name = null;
@Override
void method1(Foo foo){
...
}
}).name = "fred";
创建新的命名类型(以替换帖子中的匿名类型)。
Java不支持这样做的方法(主要是:Java不支持有用的类型推断),尽管以下方法确实有效,即使不是很有用:
{
class MyFooBar extends FooBar{
String name = null;
...
};
MyFooBar fooBar = new MyFooBar();
fooBar.name = "Test";
}
快乐的编码。
Scala和C#都支持所需的类型推断,因此支持局部变量的匿名类型特化。 (尽管C#不支持匿名扩展现有类型)。但是,Java没有。
本地班级会这样做
@SafeVarargs
public static <T> void runWithObject(T object, Consumer<T>... progs) {
for (Consumer<T> prog : progs)
prog.accept(object);
}
试试这个。
runWithObject(
new FooBar() {
String name = null;
@Override
void method1(Foo foo) {
System.out.println("name=" + name);
}
},
object -> object.name = "Test",
object -> object.method1(new Foo())
);
和
name=Test
结果:
var
或者你可以在Java 10或更高版本中使用这样的var fooBar = new FooBar() {
public String name = null;
@Override
void method1(Foo foo) {
System.out.println("name=" + name);
}
};
fooBar.name = "Test";
fooBar.method1(new Foo());
。
fooBar
foobar
是对name
类型的对象的引用,并且此类对象没有字段this
。就那么简单。由于它是一个匿名类型,引用该字段的唯一方法是通过其foobar
引用。
你正在创建一个foobar
类型的对象。编译器只知道为类/接口fooBar
定义的成员。
请记住,java是一种静态语言,而不是动态语言。它不会在运行时检查对象是否存在,它会在编译时根据类型声明进行检查。
foobar
类型是FooBar
,它没有这样的变量,因此代码无法编译。您可以通过反射访问它。
正如大家所说,这是由于静态类型和name
类不包含MyTask() //This is a method
{
new Thread(new Runnable() { //Anonymous class
public void run()
{}
}).start();
}
。所以它不会起作用。
我想指出Anonymous类的建议用法。
匿名类(或接近闭包,也许是lambdas。相似但不相同)来自函数式编程范例,其中状态应该是不可变的。
话虽这么说,你为什么要用这样的课程?当你需要快速而简短的事情时,不一定要完整的课程。例:
scope of the variables defined in the Anonymous class (or closed-over function) should only be used inside the Anonymous class
将实现仅包含在函数/类中的理解很重要。
fooBar.name = "Test";
,无法从其他程序代码访问。
因此,你不应该(并且无论如何不能)设置Boolean var= new anonymousClass(){
private String myVar; //String for example
@Overriden public Boolean method(int i){
//use myVar and i
}
public String setVar(String var){myVar=var; return this;} //Returns self instane
}.setVar("Hello").method(3);
你也可以这样做
qazxswpoi