【问题标题】:Java Passing in Type as Function ParameterJava 将类型作为函数参数传入
【发布时间】:2015-07-01 16:07:24
【问题描述】:

我来自 Python 背景,在 Python 中,您可以将对象的类型作为参数传递。但是在 Java 中你不能这样做,关于如何让这样的东西工作的任何提示?

private void function(Type TypeGoesHere)
    Stock s = new TypeGoesHere();
    s.analyze();
}

【问题讨论】:

标签: java


【解决方案1】:

Java 不支持 Python 引用函数和类的方式。要实现这种行为,您必须使用两种高级技术:泛型和反射。解释这些概念超出了 SO 答案的范围。您应该阅读 Java 指南以了解它们。

这里是一个例子,假设给定的类有一个无参数的构造函数:

public <T extends Stock> void analyzeNewStock(Class<T> clazz) throws Exception {
  Stock s = clazz.newInstance();
  s.analyze();
}

然后用analyzeNewStock(MyStock.class)调用这个函数。

由于这是一种相当复杂且容易出错的方法,您宁愿定义一个创建 Stock 实例的接口:

public interface StockProvider {
  Stock createStock(String value);
}

public class MyStockProvider implements StockProvider {
  private final String valueTwo;

  public MyStockProvider(String valueTwo) {
    this.valueTwo = valueTwo;
  }

  @Override
  public Stock createStock(String valueOne) {
    return new MyStock(valueOne, valueTwo);
  }
}

public class MyOtherClass {
  public void analyzeNewStock(StockProvider provider) {
    provider.createStock("Hi!").analyze();
  }

  public static void main(String[] args) {
    analyzeNewStock(new MyStockProvider("Hey!"));
  }
}

【讨论】:

  • 如果有参数传入 Stock 类,代码会是什么样子?
  • @budi 我更新了第二个示例。实现取决于参数是始终具有相同的值 (valueTwo) 还是可以不同 (valueOne)。
  • @budi 如果你想使用第一个例子(我不建议这样做),你会写 e。 G。 clazz.getConstructor(String.class, String.class).newInstance("Hey", "ho");.
  • 我搞定了,你的代码很好用,谢谢!令人失望的是,在 Java 中没有更简单的方法可以做到这一点(我非常想念 Python)。
  • 这个答案不需要泛型。如果您遵循擦除将对此代码执行的操作,只需传入“Stock”的基本类型参​​数将具有与泛型版本相同的效果。
【解决方案2】:

在 Java 中,您可以传递一个类。你可以这样做:

private void function(Class c)

虽然这不是很常见的程序。通过研究策略模式或正确使用面向对象编程(多态性),您可能会得到您需要的东西。

如果您正在寻找构建对象的方法,请查看工厂模式。

如果您想创建一个通用类,请查看以下详细答案:https://stackoverflow.com/a/1090488/1611957

【讨论】:

    【解决方案3】:

    您可以使用generics。例如:

    private <T> void function(Class<T> clazz) {
        try{
            T t = clazz.newInstance();
            //more code here
        }catch(InstantiationException | IllegalAccessException ex){
            ex.printStackTrace();
        }
    }
    

    Class&lt;T&gt; clazz 显示要实例化的类型。 try/catch 只是为了防止错误停止您的代码。在this SO post 中扩展了相同的想法。更多信息here.

    但是,我不确定您为什么要这样做。使用简单的界面应该很容易找到解决方法。因为你已经知道你想要一个类型为Stock 的对象,你可以传递一个接口的实现。例如:

    //interface to implement
    public interface Stock {
        public void analyze();
    }
    
    //rewrite of function
    private void function(Stock s){
        s.analyze();
    }
    

    并使用两种方式调用function

    //first way
    public class XYZ implements Stock{
        public void analyze(){
            //some code here
        }
    }
    
    //calling the function
    function(new XYZ());
    
    //second way
    function(new Stock(){
        public void analyze(){
            //your code here
        }
    });
    

    【讨论】:

    • 单靠泛型不会做他想做的事。泛型是编译时的,他想要的是比泛型更多的反射。
    • 很公平,但不管怎样,界面可能更好。
    猜你喜欢
    • 2018-01-04
    • 1970-01-01
    • 2022-10-06
    • 1970-01-01
    • 2019-03-05
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多