使用Java中构造函数参数中的新关键字是如何工作的?

huangapple go评论133阅读模式
英文:

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:

  1. what is the use of the $ sign, is it just a naming convention or does it signifies something functionally?
  2. 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:

  1. what is the use of the $ sign, is it just a naming convention or does it signifies something functionally?

  2. 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.

huangapple
  • 本文由 发表于 2023年4月11日 13:15:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75982589.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定