英文:
How does using a new keyword in constructor parameter works in java?
问题
I was learning spring security and came across this class:
org.springframework.security.core.userdetails.User$UserBuilder
here I was confused about two things:
- what is the use of the $ sign, is it just a naming convention or does it signifies something functionally?
- In the same class there is a constructor like this:
User$UserBuilder(new org.springframework.security.core.userdetails.User(){} x0) { }
here we are using the new keyword for the parameter. what does it mean?
I tried to search for it on the web but no luck
英文:
I was learning spring security and came across this class:
org.springframework.security.core.userdetails.User$UserBuilder
here I was confused about two things:
-
what is the use of the $ sign, is it just a naming convention or does it signifies something functionally?
-
In the same class there is a constructor like this:
User$UserBuilder(new org.springframework.security.core.userdetails.User(){} x0) {
}here we are using the new keyword for the parameter. what does it mean?
I tried to search for it on the web but no luck
答案1
得分: 2
你正在查看反编译的代码并尝试学习。
这是一个非常糟糕的想法;反编译器通常没有很好地维护,因此会产生一些奇怪的结构,通常是不合法的(例如这种情况 - 它无法编译)。如果你了解Java类文件格式的细节,你可能可以弄清楚,但这相当复杂,很少有用,因此作为新手或中级程序员不应该学习的东西。
给定:
package com.foo;
class Bar {
class Baz {
public Baz() {}
}
}
在编译时,它会变成__2__个类文件,因为在类文件级别上,内部类根本不存在。javac通过生成大量代码来使其工作,使其看起来就像它们存在一样。这实际上分解为两个不同的类:
package com.foo;
class Bar {
}
和
package com.foo;
class Bar$Baz {
private final Bar this$Bar;
public Bar$Baz(Bar this$Bar) {
this.this$Bar = this$Bar;
}
}
毕竟,从非静态内部类,你可以引用外部类的实例方法。你必须在某个地方调用它们,因此你需要一个包含类的实例,这就是this$Bar
字段的作用。
你正在看到的是一个糟糕的反编译器的结果,它反编译了:
new User().new User.UserBuilder();
这是有效的Java代码,但很少使用 - 它正在构造一个新的非静态内部类(User.UserBuilder
)并显式传递外部类(User
)的实例作为其容器。通常,你会在User
的某个非静态上下文中,只需调用new UserBuilder()
,这等同于this.new UserBuilder()
。
Spring是开源的,因此你的方法实际上没有什么意义。只需...查看源代码:User.java的源代码。
请注意,UserBuilder类实际上是static
的,因此显然反编译器完全混淆了。鉴于它是静态的,没有外部的'实例'可供引用,因此不需要非常奇怪的instanceOfOuter.new Inner()
语法,然而,反编译器显然认为正在发生这种情况(在Java代码中,也不在类文件中没有接受User对象的UserBuilder构造函数)。
英文:
You're looking at decompiled code and trying to learn.
That is a very bad idea; decompilers aren't maintained particularly well, and as a result produce some weird constructs, often straight up illegal (such as this - it wouldn't compile). If you know the details about the java class file format you can figure it out, but, that's... fairly complicated to learn and rarely useful, so, not something you should be learning as a newbie or even a medium-level programmer.
Given:
package com.foo;
class Bar {
class Baz {
public Baz() {}
}
}
turns into 2 classfiles when you compile it, because at the class file level, inner classes simply aren't a thing. javac makes it work by generating lots of sugar to make it look like they exist. It boils down to having 2 separate classes:
package com.foo;
class Bar {
}
and
package com.foo;
class Bar$Baz {
private final Bar this$Bar;
public Bar$Baz(Bar this$Bar) {
this.this$Bar = this$Bar;
}
}
After all, from a non-static inner class, you can refer to instance methods from your outer class. You have to call those on something, so you need an instance of your containing class, that's what that this$Bar
field is all about.
What you're looking at, is the result of a crappy decompiler that decompiled:
new User().new User.UserBuilder();
Which is valid java but very rarely used - it's constructing a new non-static inner class (User.UserBuilder
) and explicitly passing along the instance of the outer class (User
) that should serve as its container. Normally, you'd be inside some non-static context within User
and just invoke new UserBuilder()
which is equivalent to just this.new UserBuilder()
.
spring is open source, thus, there is very much no point in your approach. Just.. check the source: source of User.java.
Note that the UserBuilder class is in fact static
so evidently the decompiler got thoroughly confused. Given that it is static, there is no 'instance of the outer' to refer to, and hence no need for the very strange instanceOfOuter.new Inner()
syntax, and yet the decompiler thought, evidently, that was happening (there is no constructor of UserBuilder that accepts a User object; not in the java code, and not in the class file either).
答案2
得分: 1
以下是您要翻译的内容:
可能是您正在查看反编译的代码或其他内容(为什么春季安全团队会使用名为 x0
的参数)
我相信您指的是User类源代码
美元符号基本上意味着UserDetails
类被定义在User
类内部(源文件中的第326行)
总的来说,在Java中美元符号是一个有效的符号来命名某个东西(例如,可以将变量命名为a$b
)
但Java编译器使用它来显示一个类是否在另一个类下定义。
英文:
It might be that you're looking at the decompiled code or something (why would anyone in spring security team use a parameter called x0
)
I believd you refer to the User class source code
The dollar sign basically means that the class UserDetails
is defined inside the class User
(line 326 in the source file)
In general a dollar character is a valid symbol to name something in Java (for instance one can name the variable a$b
But java compiler uses this to show that one class is defined under another.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论