Java: возвращаемый класс (не экземпляр) - PullRequest
10 голосов
/ 19 декабря 2009

Можно ли в статическом методе вернуть класс? Я объясню ...

У меня есть:

public class A { public static void blah(){} }
public class B { }

Я хочу создать статический метод в B, который возвращает A. Так что вы можете сделать:

A.blah();

И

B.getA().blah();

Это без создания экземпляра A. Просто используйте статические методы.

Возможно ли это?

Ответы [ 9 ]

7 голосов
/ 20 декабря 2009

Это опровержение ответа @ irreputable:

public class B { 
    public static A getA(){ return null; }
}

B.getA().blah(); //works!

Это "работает", но, вероятно, не в том смысле, в котором вы ожидаете, и, конечно, не в полезной форме. Давайте разберем это на две части:

A a = B.getA();
a.blah();

Первый оператор возвращает (в данном случае нулевой) экземпляр A, а второй оператор игнорирует этот экземпляр и вызывает A.blah(). Итак, эти утверждения на самом деле эквивалентны

B.getA();
A.blah();

или (учитывая, что getA() не имеет побочных эффектов), просто

A.blah();

А вот пример, который иллюстрирует это более четко:

public class A {
   public static void blah() { System.err.println("I'm an A"); }
}

public class SubA extends A {
   public static void blah() { System.err.println("I'm a SubA"); }
}

public class B { 
   public static A getA(){ return new SubA(); }
}

B.getA().blah(); //prints "I'm an A".

... и это (я надеюсь) иллюстрирует, почему этот подход не решает проблему ОП.

6 голосов
/ 19 декабря 2009

Я собираюсь догадаться, что причина, по которой вы спрашиваете это, заключается в том, что вы хотите, чтобы B возвращал много разных классов с различным поведением - не только A.

Вы, вероятно, хотите использовать интерфейс для того, что вы делаете вместо этого.

interface IA {
  void blah();
}

public class B {
  IA getA1() {
     return new IA {
        void blah() {
           ...code...
        }
     }
  }
  IA getA2() {
     ...
  }
  IA getA3() {
     ...
  }
}

myCallingMethod {
   B.getA1().blah();
   B.getA2().blah();
   B.getA3().blah();
}
6 голосов
/ 19 декабря 2009

Нет, это невозможно. У вас есть два варианта:

  1. B.getA() возвращает экземпляр А, а blah() будет нестатичным способ.

  2. Прямой вызов A.blah().

4 голосов
/ 19 декабря 2009

Люди говорят, что это невозможно, и это своего рода правда, но если вы используете API отражения, вы можете сделать что-то похожее на это.

Вот как ты мог это сделать.

У вас есть класс, который делает это.

public class B { 
   Class a
   public static Class getA(){
      return a; 
    }
}

тогда, чтобы позвонить бла, вы делаете:

try{
   Method m = B.getA().getDeclaredMethod("blah");
   m.invoke(null);//for a static method, you can invoke on null
}
Catch(Exception e){
   // see documentation for list of exceptions
}

Итак, почему вы хотите это сделать? Что ж, если вы сделаете это таким образом, вы можете изменить класс A на So, так что getA () может вернуть A, B, C или D, все с различными функциями blah (). Я не совсем уверен, какой цели это послужит, но если вы хотите это сделать, вы можете.

см: Class.getDeclaredMethod () и Method.invoke () для получения дополнительной информации.

Я не пробовал этого, так что вам, возможно, придется внести некоторые изменения.

2 голосов
/ 19 декабря 2009

Даже если бы это было возможно, это не принесет особой пользы. Вызов A.blah() не создает экземпляр A. Это статический метод, для которого не нужен экземпляр.

И вы не можете использовать интерфейсы для реализации статических методов. Так для чего это должно быть хорошо?

2 голосов
/ 19 декабря 2009

Нет, это невозможно. Вы можете только вернуть ссылку на экземпляр класса. Самое близкое, что вы можете получить, это вернуть ссылку на переменную типа Class. Вопрос: зачем тебе это? Какую проблему ты пытаешься решить? Там может быть лучшее решение.

1 голос
/ 19 декабря 2009
public class B { 
    public static A getA(){ return null; }
}

B.getA().blah(); //works!

EDIT

Это правда, что это эквивалентно

B.getA();
A.blah();

За исключением того, что они выглядят совсем по-другому. Представьте, что у вас есть цепочка из них.

Я проверил org.apache.commons.cli.OptionBuilder и лично я бы так не поступил, но у автора есть свое дело. API используется только в начале программы, в одном потоке.

Разработчикам API иногда приходится делать какие-то волшебные шаги, не слишком осуждайте их.

1 голос
/ 19 декабря 2009

Если вы не хотите иметь экземпляр A, тогда позвольте B вызвать blah() напрямую. * Т.е. 1004 *

class B { 
    void blah() { 
        A.blah();
    } 
}
0 голосов
/ 19 декабря 2009

Вы можете вернуть метод, используя отражение, которое вы можете вызвать () позже. Тем не менее, похоже, что вы пытаетесь сделать что-то, что должно быть сделано по-другому. Почему вы пытаетесь это сделать?

...