자바의 익명 코드 블록
Java에서 익명 코드 블록을 실제로 사용합니까?
public static void main(String[] args) {
// in
{
// out
}
}
이것은 명명 된 블록 에 대한 것이 아닙니다.
name: {
if ( /* something */ )
break name;
}
.
변수 범위를 제한합니다.
public void foo()
{
{
int i = 10;
}
System.out.println(i); // Won't compile.
}
그러나 실제로 이러한 코드 블록을 사용하는 경우에는 해당 블록을 메서드로 리팩토링하려는 신호일 수 있습니다.
@David Seiler의 대답은 옳지 만 코드 블록은 매우 유용하며 자주 사용되어야하며 반드시 메서드를 고려할 필요성을 나타내지는 않는다고 주장합니다. 스윙 컴포넌트 트리를 구성하는 데 특히 유용합니다. 예 :
JPanel mainPanel = new JPanel(new BorderLayout());
{
JLabel centerLabel = new JLabel();
centerLabel.setText("Hello World");
mainPanel.add(centerLabel, BorderLayout.CENTER);
}
{
JPanel southPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0,0));
{
JLabel label1 = new JLabel();
label1.setText("Hello");
southPanel.add(label1);
}
{
JLabel label2 = new JLabel();
label2.setText("World");
southPanel.add(label2);
}
mainPanel.add(southPanel, BorderLayout.SOUTH);
}
코드 블록은 변수의 범위를 가능한 한 엄격하게 제한 할뿐만 아니라 (특히 변경 가능한 상태 및 최종 변수가 아닌 변수를 처리 할 때 항상 좋습니다) XML / HTML 작성과 같은 방식으로 구성 요소 계층 구조를 보여줍니다. 코드를 읽고 작성하고 유지하기가 더 쉽습니다.
각 구성 요소 인스턴스화를 메서드로 팩터링하는 것과 관련된 내 문제는
- 이 메서드는 개인 인스턴스 메서드 인 경우에도 한 번만 사용되지만 더 많은 청중에게 노출됩니다.
- 더 깊고 복잡한 구성 요소 트리를 상상하면 읽기가 더 어려워지고, 관심있는 코드를 찾기 위해 드릴 다운 한 다음 시각적 컨텍스트를 풀어야합니다.
이 Swing 예제에서 복잡성이 실제로 관리 용이성을 넘어 서면 트리의 분기를 여러 개의 작은 메서드가 아닌 새로운 클래스로 추출 할 때임을 나타냅니다.
일반적으로 지역 변수의 범위를 가능한 한 작게 만드는 것이 가장 좋습니다 . 익명 코드 블록이 도움이 될 수 있습니다.
나는 이것이 switch
진술 과 함께 특히 유용하다고 생각 합니다. 익명 코드 블록이없는 다음 예제를 고려하십시오.
public String manipulate(Mode mode) {
switch(mode) {
case FOO:
String result = foo();
tweak(result);
return result;
case BAR:
String result = bar(); // Compiler error
twiddle(result);
return result;
case BAZ:
String rsult = bar(); // Whoops, typo!
twang(result); // No compiler error
return result;
}
}
그리고 익명의 코드 블록 :
public String manipulate(Mode mode) {
switch(mode) {
case FOO: {
String result = foo();
tweak(result);
return result;
}
case BAR: {
String result = bar(); // No compiler error
twiddle(result);
return result;
}
case BAZ: {
String rsult = bar(); // Whoops, typo!
twang(result); // Compiler error
return result;
}
}
}
나는 두 번째 버전이 더 깨끗하고 읽기 쉽다고 생각합니다. 그리고 스위치 내에서 선언 된 변수의 범위를 선언 된 경우로 줄입니다. 내 경험상 99 %의 시간을 원합니다.
그러나 경고가 발생하더라도 케이스 폴 스루에 대한 동작은 변경 되지 않습니다 . break
또는이 return
를 방지하려면를 포함해야 합니다.
나는 당신과 / 또는 다른 대답이 두 가지 별개의 구문 구조를 혼동하고 있다고 생각합니다. 즉 인스턴스 이니셜 라이저 및 블록입니다. (그런데 "명명 된 블록"은 실제로 레이블이있는 명령문이며, 여기서 명령문은 블록이됩니다.)
인스턴스 이니셜 라이저는 클래스 멤버의 구문 수준에서 사용됩니다. 예 :
public class Test {
final int foo;
{
// Some complicated initialization sequence; e.g.
int tmp;
if (...) {
...
tmp = ...
} else {
...
tmp = ...
}
foo = tmp;
}
}
Initializer 구문은 @dfa의 예제에 따라 익명 클래스와 함께 가장 일반적으로 사용됩니다. 또 다른 사용 사례는 '최종'속성의 복잡한 초기화를 수행하는 것입니다. 예를 들어 위의 예를 참조하십시오. (그러나 일반 생성자를 사용하는 것이 더 일반적입니다. 위의 패턴은 정적 이니셜 라이저에서 더 일반적으로 사용됩니다.)
다른 구조는 일반 블록이며 메소드와 같은 코드 블록 내에 나타납니다. 예 :
public void test() {
int i = 1;
{
int j = 2;
...
}
{
int j = 3;
...
}
}
블록은 명령문 시퀀스를 그룹화하기 위해 제어문의 일부로 가장 일반적으로 사용됩니다. 그러나 위에서 사용하면 선언의 가시성을 제한 할 수 있습니다. 예 j
를 들어 위의.
이것은 일반적으로 코드를 리팩토링해야 함을 나타내지 만 항상 명확한 것은 아닙니다. 예를 들어, Java로 코딩 된 인터프리터에서 이러한 종류의 것을 볼 수 있습니다. 스위치 암의 명령문은 별도의 메소드로 고려 될 수 있지만 이는 인터프리터의 "내부 루프"에 대해 상당한 성능 저하를 초래할 수 있습니다. 예 :
switch (op) {
case OP1: {
int tmp = ...;
// do something
break;
}
case OP2: {
int tmp = ...;
// do something else
break;
}
...
};
익명 내부 클래스의 생성자로 사용할 수 있습니다.
이렇게 :
이렇게하면 개체 생성 중에 사용 가능한 블록이 실행되기 때문에 개체를 초기화 할 수 있습니다.
익명의 내부 클래스로 제한되지 않고 일반 클래스에도 적용됩니다.
public class SomeClass {
public List data;{
data = new ArrayList();
data.add(1);
data.add(1);
data.add(1);
}
}
익명 블록은 변수의 범위를 제한하고 이중 중괄호 초기화에 유용합니다 .
비교
Set<String> validCodes = new HashSet<String>();
validCodes.add("XZ13s");
validCodes.add("AB21/X");
validCodes.add("YYLEX");
validCodes.add("AR2D");
와
Set<String> validCodes = new HashSet<String>() {{
add("XZ13s");
add("AB21/X");
add("YYLEX");
add("AR5E");
}};
인스턴스 이니셜 라이저 블록 :
class Test {
// this line of code is executed whenever a new instance of Test is created
{ System.out.println("Instance created!"); }
public static void main() {
new Test(); // prints "Instance created!"
new Test(); // prints "Instance created!"
}
}
익명 초기화 블록 :
class Test {
class Main {
public void method() {
System.out.println("Test method");
}
}
public static void main(String[] args) {
new Test().new Main() {
{
method(); // prints "Test method"
}
};
{
//=========================================================================
// which means you can even create a List using double brace
List<String> list = new ArrayList<>() {
{
add("el1");
add("el2");
}
};
System.out.println(list); // prints [el1, el2]
}
{
//==========================================================================
// you can even create your own methods for your anonymous class and use them
List<String> list = new ArrayList<String>() {
private void myCustomMethod(String s1, String s2) {
add(s1);
add(s2);
}
{
myCustomMethod("el3", "el4");
}
};
System.out.println(list); // prints [el3, el4]
}
}
}
변수 범위 제한 :
class Test {
public static void main() {
{ int i = 20; }
System.out.println(i); // error
}
}
블록을 사용하여 부모 범위에서 최종 변수를 초기화 할 수 있습니다. 이것은 단일 변수를 초기화하는 데만 사용되는 일부 변수의 범위를 제한하는 좋은 방법입니다.
public void test(final int x) {
final ClassA a;
final ClassB b;
{
final ClassC parmC = getC(x);
a = parmC.getA();
b = parmC.getB();
}
//... a and b are initialized
}
일반적으로 블록을 메서드로 이동하는 것이 좋지만이 구문은 여러 변수를 반환해야하고 래퍼 클래스를 만들고 싶지 않은 일회성 경우에 유용 할 수 있습니다.
참고 URL : https://stackoverflow.com/questions/1563030/anonymous-code-blocks-in-java
'IT박스' 카테고리의 다른 글
Protobuf가 공유 라이브러리를 찾을 수 없습니다. (0) | 2020.11.29 |
---|---|
정수 목록을 하나의 숫자로 변환 하시겠습니까? (0) | 2020.11.29 |
아코디언을 열어 두도록 Twitter Bootstrap 축소 플러그인 수정 (0) | 2020.11.29 |
웹 사이트에서 C #으로 파일을 다운로드하는 방법 (0) | 2020.11.29 |
React 컴포넌트를 조건부로 래핑하는 방법은 무엇입니까? (0) | 2020.11.28 |