2012-12-28 11 views
8

Powiel możliwe:
Why does this() and super() have to be the first statement in a constructor?„wywołanie konstruktora musi być pierwszą instrukcją w konstruktorze” problem w Javie

Chciałabym mieć łańcuch konstruktora w Javie. Na przykład, przy pierwszym konstruktorze jako parametr mam ciąg i wywołuję drugi konstruktor, gdy tworzę obiekt z ciągu parametrów.

public class IMethodFinder { 
    public IMethodFinder(String projectName, String methodName, 
     int numberOfParameters) { 
     IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); 
     IJavaProject javaProject = JavaCore.create(project); 
     this(javaProject, methodName, numberOfParameters); 
    } 

    public IMethodFinder(IJavaProject javaProject, String methodName, 
     int numberOfParameters) { 
     ... 
    } 
} 

Jednak otrzymałem komunikat o błędzie "Błąd konstruktora musi być pierwszym stwierdzeniem w konstruktorze".

enter image description here

zrobiłem wspólny kod, który jest współdzielony między dwoma konstruktorów, ale nie jestem pewien, że to jedyne rozwiązanie, aby ominąć ten problem.

public class IMethodFinder { 
    public IMethodFinder(IJavaProject javaProject, String methodName, 
      int numberOfParameters) { 
     dosomething(javaProject, methodName, numberOfParameters); 
    } 

    public IMethodFinder(String projectName, String methodName, 
      int numberOfParameters) { 
     IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); 
     IJavaProject javaProject = JavaCore.create(project); 
     dosomething(javaProject, methodName, numberOfParameters); 
    } 

    private void dosomething(IJavaProject javaProject, String methodName, 
      int numberOfParameters) 
    { 
     ... 
    } 

} 
  • Dlaczego Java wymaga połączenia konstruktora jako pierwsze pismo? Jaka jest idea tego wymagania?
  • Co to jest konwencja Java dla mojej sprawy? Czy popularna metoda wywoływania to dobra droga?
+2

tak, wywołanie 'init () 'funkcja od twojego konstruktora jest wspólna. –

+1

Można po prostu przepisać treść pierwszego konstruktora jako: 'this (JavaCore.create (ResourcesPlugin.getWorkspace(). GetRoot(). GetProject (projectName)), methodName, numberOfParameters);' – Alex

Odpowiedz

14

Nie ma wewnętrzny powód, Java nie może być przedłużony, aby umożliwić oświadczenia, że ​​nie korzysta this przed konstruktora. To jednak zwiększy złożoność języka i zasłoni kod po jego użyciu (szczególnie jeśli uważasz, że połączenie może być niejawne).

Ogólnie rzecz biorąc, chcesz, aby konstruktory były tak proste, jak to tylko możliwe. init() metody są złym pomysłem, ponieważ uniemożliwiają korzystanie z final. Wygląda na to, że kod uzyskuje dostęp do zmiennej statycznej, co jest naprawdę złym pomysłem.

dla konkretnego kodu, można napisać:

public IMethodFinder(String projectName, String methodName, 
     int numberOfParameters) { 
     this(
      JavaCore.create(
       ResourcesPlugin.getWorkspace().getRoot().getProject(projectName) 
      ), 
      methodName, 
      numberOfParameters 
     ); 
    } 

Bardziej ogólnie Hack jest do wywołania metody statyczne w wywołaniu konstruktora:

public class IMethodFinder { 
    public IMethodFinder(String projectName, String methodName, 
     int numberOfParameters) { 
     this(createProject(projectName), methodName, numberOfParameters); 
    } 

    public IMethodFinder(IJavaProject javaProject, String methodName, 
     int numberOfParameters) { 
     ... 
    } 

    private static IJavaProject createProject(String projectName) { 
     IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); 
     IJavaProject javaProject = JavaCore.create(project); 
     return javaProject; 
    } 
} 
+3

+1 dla "nie ma wewnętrzny powód, dla którego nie można rozszerzyć Java, aby zezwalać na instrukcje, które nie mają dostępu do tego przed konstruktorem ". – Pacerier

2

Rozwiązanie 1: Twoi konstruktorzy powinni mieć lepiej ukierunkowany przepływ, aby uniknąć używania zwykłego init. Dość często jeden konstruktor będzie bardziej podstawowy i skonstruuje kompletny poprawny obiekt, a następnie zewnętrzny dekorator może to udekorować.

Rozwiązanie 2: Często dobrą praktyką jest stosowanie statycznej metody fabrycznej, która na przykład obsługuje przetwarzanie wstępne, którego potrzebujesz tutaj. To wygląda na dobry przypadek użycia dla tego wzoru.

Rozwiązanie 3: Zamiast zwykłej metody init po prostu masz statyczne metody, które wykonują dla Ciebie izolowany preprocessing. na przykład myField = processInputField(myField). Typowe metody grają bardzo słabo przy końcowych polach, co jest silniejszym powodem, dla którego są złą praktyką - zasadniczo tak, konstruktorzy powinni wykonywać całą pracę konstruowania.

1

zobaczyć this answer do 1st pytanie jak za 2 pytania - tak stosunkowo akceptowane użyć jakieś metody init() dla tych przypadkach

Powiązane problemy