문제

Java는 클래스 멤버 변수를 선언하고 초기화 할 때 발생할 수있는 예외를 관리하기위한 구문이 있습니까?

public class MyClass
{
  // Doesn't compile because constructor can throw IOException
  private static MyFileWriter x = new MyFileWriter("foo.txt"); 
  ...
}

또는 그러한 초기화는 항상 우리가 선언 할 수있는 방법으로 이동해야합니까? throws IOException 아니면 초기화를 트리 캐치 블록으로 랩핑 하시겠습니까?

도움이 되었습니까?

해결책

정적 초기화 블록을 사용하십시오

public class MyClass
{
  private static MyFileWriter x;

  static {
    try {
      x = new MyFileWriter("foo.txt"); 
    } catch (Exception e) {
      logging_and _stuff_you_might_want_to_terminate_the_app_here_blah();
    } // end try-catch
  } // end static init block
  ...
}

다른 팁

이러한 종류의 초기화를 예외를 처리 할 수있는 방법으로 이동하는 것이 가장 좋습니다.

정적 인 심혈제에서 던져진 예외는 설계 문제를 나타낼 수 있습니다. 실제로 파일을 정적으로로드하려고 시도해서는 안됩니다. 또한 정적은 일반적으로 변이해서는 안됩니다.

예를 들어, Junit 3.8.1로 다시 작업하면 애플릿/WebStart에서 거의 사용할 수 있지만 파일 액세스를 수행하는 한 정적 이니셜 라이저로 인해 실패했습니다. 관련된 클래스의 나머지 부분은 컨텍스트에 맞게 적합했습니다. 컨텍스트에 맞지 않고 전체 프레임 워크를 날려 버리는 것은이 정적입니다.

예외가 발생하는 합법적 인 경우가 있습니다. 환경에 특정 기능이없는 경우, 예를 들어 이전 JDK이기 때문에 구현을 대체하고 싶을 수도 있고 평범한 것은 없습니다. 클래스가 실제로 borked 인 경우, 깨진 클래스가 존재하지 않고 검사되지 않은 예외를 던지십시오.

귀하의 선호도와 당면한 문제에 따라, 그 주위를 둘러 볼 수있는 두 가지 일반적인 방법이 있습니다 : 명시 적 정적 이니셜 라이저와 정적 방법. (저는 대부분의 사람들이 전자를 선호한다고 생각합니다. 조쉬 블로 치는 후자를 선호한다고 생각합니다.)

private static final Thing thing;

static {
    try {
        thing = new Thing();
    } catch (CheckedThingException exc) {
        throw new Error(exc);
    }
}

또는

private static final Thing thing = newThing();

private static Thing newThing() {
    try {
        return new Thing();
    } catch (CheckedThingException exc) {
        throw new Error(exc);
    }
}

참고 : 정적은 최종적이어야합니다 (일반적으로 불변). 최종적으로, 친절한 컴파일러는 올바른 단일 할당을 확인합니다. 명확한 할당은 깨진 예외 처리 - 랩 및 던지기, 인쇄/로그를 작성하지 않을 수 있음을 의미합니다. 이상하게도, 당신은 클래스 이름을 사용하여 정적 이니셜 라이저에서 클래스 이름으로 초기화를받을 수 없습니다 (이에 대한 좋은 이유가 있다고 확신합니다).

인스턴스 이니셔는 비슷하지만 생성자를 던질 수 있지만 이니셔를 생성자 내에 넣을 수 있습니다.

이 건축은 당신이 발견 한 것처럼 불법입니다. 생성자가 예외를 예외로 던지는 멤버는 생성자, 인스턴스 이니셜 라이저, 또는 정적 멤버의 경우 정적 이니셜 라이저와 같은 예외 처리를 허용하는 경우를 제외하고는 확인 된 예외를 제외 할 수 없습니다.

그래서 이것은 법적 방법이 될 것입니다.

public class MyClass {
    MyFileWriter x;
    {
        try {
            x = new MyFileWriter("foo.txt");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    ...
}

합법적이지만 오히려 추악합니다. 생성자에서 초기화하고 예외를 선언하는 선호를 원하거나 사용자가 메소드를 호출하여 명시 적으로 초기화하는 것을 선호합니다. 그러나 사용자가이를 초기화 해야하는 경우 객체가 유효하지 않을 가능성에 대한 종속 방법을 설명해야합니다.

당신이 글을 쓰고 있다면 MyClass 포장지로 MyFileWriter, 나는 생성자에서 초기화를한다고 말할 것입니다. 그렇지 않으면 먼저 물체의 전체 수명 동안 작가가 열려야하는지 의문을 제기 할 것입니다. 이것을 제거하는 것이 가능할 수 있습니다.

편집하다: 내가 이것을 쓸 때, "static"현장에 추가되지 않았다. 이것은 조금만 바뀌는 것 : 나는 왜 지구상에서 작가가 클래스 로더 평생. 어떻게 폐쇄 될 수 있습니까?

이것은 일종의 집에서 재배 한 벌목 시스템입니까? 그렇다면, 나는 당신이 java.util.logging 또는 많은 훌륭한 타사 로깅 프레임 워크 중 하나.

공장 방법을 제안합니다.

  public class MyClass{
      private static MyFileWriter fileWriter = MyFileWriter.getFileWriter("foo.txt");

  }

  public class MyFileWriter {
     /*
      * Factory method. Opens files, etc etc 
      * @throws IOException.
      */
     public static MyFileWriter getFileWriter(String path) throws IOException{

        MyFileWriter writer  = new FileWriter();

       //stuff that can throw IOException here.

       return writer;
     }

   /*protected constructor*/
    protected MyFileWriter(){

     //build object here.

    } 
  }

필드 초기화에서 예외를 처리하는 또 다른 방법이 있습니다. MyFileWriter 생성자가 예외를 던지는 경우를 고려해 보자. 참조 용이 샘플 코드를 고려하십시오.

import java.io.IOException;
public class MyFileWriter {
    public MyFileWriter(String file) throws IOException{
         throw new IOException("welcome to [java-latte.blogpspot.in][1]");
    }
}

우리가 이런 파일을 초기화하려고한다면 .....

public class ExceptionFields{
    MyFileWriter f = new MyFileWriter("Hello");

}

컴파일러는이를 초기화 할 수 없습니다. 정적 블록에서 초기화를하는 대신 이렇게 할 수 있습니다.

ioexception을 던지는 기본 생성자를 선언하십시오

import java.io.IOException;
public class ExceptionFields{
    MyFileWriter f = new MyFileWriter("Hello");
    public ExceptionFields() throws IOException{    

    }    
}

이것은 MyFileWriter 객체를 초기화합니다.

클래스에 생성자가 하나만 있으면 일반적으로 해당 초기화기를 해당 생성자로 옮깁니다.

클래스에 하나 이상의 생성자가있는 경우 초기화 블록을 사용합니다.

public class MyClass {
   private static MyFileWriter x;

   // initialization block start here
   {
       try {
          x = new MyFileWriter("..");
       } catch(Exception e) {
         // exception handling goes here
       }
   }

   public MyClass() { 
    // ctor #1
   }

   public MyClass(int n) { 
     // ctor #2
   }
}

이니에 대한 좋은 점. 블록은 모든 생성자의 시작 부분에 "주입"된다는 것입니다. 따라서 초기화기를 복제 할 필요가 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top