Java大括号初始化对象

Java Double Brace Initialization

1. 创建和初始化不带双大括号的对象

您不觉得Java应该为集合(List、Map、Set等)提供更方便的语法吗。我之所以这么说,是因为每次如果我们必须在代码中使用集合,那么我们就必须执行以下操作-

为临时集合声明变量

创建一个新的空集合,并在变量中存储对它的引用

把东西收藏起来

将集合传递给方法

例如:WithoutDoubleBrace.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.HashSet;
import java.util.Set;

public class WithoutDoubleBrace
{
public static void main(String[] args)
{
Set<String> params = new HashSet<String>();
params.add("param one");
params.add("param two");
params.add("param three");
params.add("param four");
// ... and so on; Now pass above collection as parameter to method or
// some other ways
useParamsInSomeMethod(params);
}

private static void useParamsInSomeMethod(Set<String> params) {
// TODO Auto-generated method stub
}
}

这些都是我们在实时编码实践中遵循的正常步骤。

2. 在“单步”中创建和初始化对象的双大括号初始化

让我们看看另一种简单的方法。这就是所谓的双大括号初始化。使用双大括号功能的语法如下:

DoubleBrace.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.HashSet;
import java.util.Set;

public class DoubleBrace
{
public static void main(String[] args)
{
Set<String> params = new HashSet<String>() {
{
add("param one");
add("param two");
add("param three");
add("param four");
}
};

// ... and so on; Now pass above collection as parameter to method or
// some other ways
useParamsInSomeMethod(params);
}

private static void useParamsInSomeMethod(Set<String> params) {
// TODO Auto-generated method stub
}
}
2.1. 内联双大括号初始化

或者更简单一些:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.HashSet;

public class DoubleBrace {
public static void main(String[] args) {

useParamsInSomeMethod(new HashSet<String>() {
{
add("param one");
add("param two");
add("param three");
add("param four");
}
});
}

private static void useParamsInSomeMethod(HashSet<String> params) {
//perform some operation
}
}
3. 双大括号初始化如何工作?

让我们了解这是如何工作的。

  • 第一个大括号创建一个新的匿名内部类。这些内部类能够访问其父类的行为。所以,在我们的例子中,我们实际上是在创建HashSet类的子类,所以这个内部类能够使用add()方法。

  • 第二组大括号只不过是初始化实例。如果您提醒核心java概念,那么您可以很容易地将实例初始值设定项块与静态初始值设定项相关联,因为类似于大括号的结构。唯一的区别是,静态初始值设定项是用static关键字添加的,并且只运行一次;不管您创建了多少个对象。

4. 总结
  1. 因为用双括号初始化的类基本上是内部类。所以我们可以为所有其他类创建它们,直到它们不是最终的。

  2. 如果没有显式修改equals()方法以使用这些类,则不应使用此类类,因为equals()方法通常也会检查类的相等性。

  3. 您应该始终记住,初始值设定项是在构造函数之前运行的(而不是在超类构造函数之前)。

  4. 您创建的匿名类的实例包含对封闭对象的合成引用。如果序列化集合,还将序列化外部类中的所有内容。

5. Java 9 工厂方法

Java 9带来了很多工厂方法,可以用来创建和初始化单个语句中的Java集合。如果您使用Java 9或更高版本,它可以是一种替代方法,也是首选方法。它消除了双支撑初始化的必要性。

1
2
3
4
5
6
7
8
List<String> names = List.of("lokesh", "rohit", "alex");

Set<String> names = Set.of("Lokesh", "Amit", "John");

Map<String, String> names = Map.ofEntries(
Map.entry("1", "Lokesh"),
Map.entry("2", "Amit"),
Map.entry("3", "Brian"));
6. Java 8 流收集器

对于Java 8和更低版本,您可以在Java流的形式中找到类似的用例。

1
2
Set<String> names = Stream.of("lokesh", "rohit", "alex")
.collect( collectingAndThen( toSet(), Collections::unmodifiableSet ) );