Как использовать тип класса параметра метода?

У меня есть следующие классы: Foo1 расширяет Bar и Foo2 расширяет панель

Я хотел бы передать тип Foo1 или Foo2 в моем методе, чтобы создать либо Foo1, либо Foo2, например:

public Bar createMethod( "either type of Foo1, or Foo2" fooType) {
    
    //returns the foo1 or foo2
}

Есть ли какой-нибудь подход для достижения этого?

Это звучит как проблема XY. Чего вы на самом деле пытаетесь достичь?

Turing85 20.12.2020 20:41
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
Что такое управление транзакциями JDBC и как оно используется для поддержания согласованности данных?
Что такое управление транзакциями JDBC и как оно используется для поддержания согласованности данных?
Управление транзакциями JDBC - это мощная функция, которая позволяет рассматривать группу операций с базой данных как единую единицу работы. Оно...
Выполнение HTTP-запроса с помощью Spring WebClient: GET
Выполнение HTTP-запроса с помощью Spring WebClient: GET
WebClient - это реактивный веб-клиент, представленный в Spring 5. Это реактивное, неблокирующее решение, работающее по протоколу HTTP/1.1.
Gradle за прокси-сервером
Gradle за прокси-сервером
Создайте проект Gradle под сетевым прокси.
0
1
72
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вы можете объявить

public Bar createMethod(Class<? extends Bar> fooType) {
    //returns the foo1 or foo2
}

А затем позвоните, как в

Bar bar = createMethod(Foo1.class);
Ответ принят как подходящий

Вы можете иметь некоторую гибкость, используя дженерики, объявив:

public <T extends Bar> T createMethod(Class<T> foo) {
    // do the factoring
    retrun (T) foo1 // (or foo2 depending on the foo passed);
} 

При этом действительны все следующие назначения:

Bar b1 = createMethod(Foo1.class);
Bar b2 = createMethod(Foo2.class);
Foo1 f1 = createMethod(Foo1.class);
Foo2 f2 = createMethod(Foo2.class);

Примечание: во время выполнения вы получите ClassCastException, если не вернете ожидаемый тип. Итак, если вы, например, сделаете это:

public <T extends Bar> T createMethod(Class<T> foo) {
    return (T)new Foo2();
}

И

Foo1 foo1 = createMethod(Foo1.class);

Вот код:

        public static void main(String args[]){

        Bar barB = createMethod(FooB.class);
        Bar barA = createMethod(FooA.class);

        System.out.println("barB is instance of B " + (barB instanceof FooB) );
        System.out.println("barA is instance of A " + (barA instanceof FooA) );

    }



    public static Bar createMethod(Class foo) {
        if (foo.equals(FooA.class)) {
            FooA fooA = new FooA();
            return (Bar) fooA;
        }
        else{
            FooB fooB = new FooB();
            return (Bar) fooB;
        }
    }

}

    class Bar{}
    
    class FooA extends Bar{}
    
    class FooB extends Bar{}

А ваши FooA и FooB расширяют Bar.

В Java нет типов объединения, поэтому тип, подобный A | B, в Java невозможен.

В Java 15 запечатанные типы были добавлены через JEP 360, поэтому вы можете создать иерархию запечатанных типов только с двумя типами, которые нельзя расширить, эффективно имитируя типы объединения для ваших собственных типов.

Передав экземпляр Class, вы можете использовать отражение для создания экземпляра типа.

public sealed interface FooBar permits Foo, Bar { }
public final class Bar implements FooBar { }
public final class Foo implements FooBar { }

public FooBar createMethod(Class<? extends FooBar> type) {
   return type.newInstance();
}

Без запечатанных типов вам придется смириться с тем фактом, что третьи стороны могут расширять ваши типы, что делает возможным использование не только двух типов в качестве параметров для метода.

Другая возможность — использовать строки и использовать Class.forName(String) для получения типа, связанного с полным классом:

public FooBar createMethod(String type) {
   if (type.equals("your.type.Foo") || type.equals("your.type.Bar"))
        return Class.forName(type).newInstance();
}

Другие вопросы по теме