Java :如果实现 T(Base)则做某事,如果 "Base" 的任何其他实现则做其他事情
Java : Do something if implementation T (of Base) and something else if any other implementation of "Base"
我有一个接口 Message
,它有两个实现 MessageA
和 MessageB
。
现在我有以下泛型 class,它采用扩展 Message
的类型变量 T
。如果参数是 T
(或子类型),我希望方法 test
以一种方式运行,如果参数是 Message
的其他实现,则以另一种方式运行:
我试过了,但是因为擦除而不起作用:
public class MyClass<T extends Message>
{
public Integer test(T m)
{
System.out.println( "This is the good one." );
return m.f(7);
}
public <S extends Message> Integer test(S m)
{
System.out.println("I'm not the good one");
return m.f(7);
}
}
我可以进行显式类型检查,但我想有一种更简洁的方法可以实现我的目标。
编辑
我更喜欢使用覆盖或重载,因为在我的项目中,我将有一个 class MyClassA implements MyClass<MessageA>
来实现方法 test(MessageA m)
。但是我想在基本泛型 class.
中实现 "wrong" 案例
作品如下:
public class MyClassA extends MyClass<MessageA>
{
public Integer test(Message m)
{
if (m instanceof MessageA)
{
return m.f(7);
}
else
{
System.out.println("Bad type.");
return 0;
}
}
}
但它迫使我在我的泛型 MyClass<T extends Message>
的每个实例化中使用 print("bad type")
实现一个 if-then
块(为了代码重复)。
编辑
基于公认的解决方案,我发布了一个功能齐全的 minimal example here.
重载是静态的。它使用 compile-time 对象类型而不是实际的 run-time 类型。要么使用 Message#test() 来使用覆盖,要么在代码中添加显式类型检查(即 instanceof)。
您可以 测试 使用 instanceof
关键字:
public Integer test(T m)
{
if(m instanceof MessageA || m instanceof MessageB) {
System.out.println( "A subclass of Message instance." );
//your custom process
}else{
System.out.println( "A Message instance." );
//your custom process
}
}
编辑
由于泛型在 Java 中的实现方式,您无法找出泛型 class 在运行时使用的对象类型(泛型类型 T 在运行时不保留) ). 仍然,您可以使用私有数据成员并在每个 Message 分支中重载您的测试方法 并在通用 Class 中使用它:
public class MyClass<T extends Message>
{
private Class<T> type;
public MyClass(Class<T> type) { this.type = type; }
public Integer test(T m)
{
return type.test(m);
}
}
我的回答可能听起来很刺耳,但你的设计似乎有点破烂。
最简单的解决方案是从一个公共的 class 派生 MessageA 和 MessageB(这可能与您的界面无关),并向此 class 添加一个受保护的函数,您可以称呼。
或者您创建第二个界面,然后回答以下问题之一。
请参阅以下 SO 问题之一:
Generic extending class AND implements interface
Java generics - Make Generic to extends 2 interfaces
我有一个接口 Message
,它有两个实现 MessageA
和 MessageB
。
现在我有以下泛型 class,它采用扩展 Message
的类型变量 T
。如果参数是 T
(或子类型),我希望方法 test
以一种方式运行,如果参数是 Message
的其他实现,则以另一种方式运行:
我试过了,但是因为擦除而不起作用:
public class MyClass<T extends Message>
{
public Integer test(T m)
{
System.out.println( "This is the good one." );
return m.f(7);
}
public <S extends Message> Integer test(S m)
{
System.out.println("I'm not the good one");
return m.f(7);
}
}
我可以进行显式类型检查,但我想有一种更简洁的方法可以实现我的目标。
编辑
我更喜欢使用覆盖或重载,因为在我的项目中,我将有一个 class MyClassA implements MyClass<MessageA>
来实现方法 test(MessageA m)
。但是我想在基本泛型 class.
作品如下:
public class MyClassA extends MyClass<MessageA>
{
public Integer test(Message m)
{
if (m instanceof MessageA)
{
return m.f(7);
}
else
{
System.out.println("Bad type.");
return 0;
}
}
}
但它迫使我在我的泛型 MyClass<T extends Message>
的每个实例化中使用 print("bad type")
实现一个 if-then
块(为了代码重复)。
编辑 基于公认的解决方案,我发布了一个功能齐全的 minimal example here.
重载是静态的。它使用 compile-time 对象类型而不是实际的 run-time 类型。要么使用 Message#test() 来使用覆盖,要么在代码中添加显式类型检查(即 instanceof)。
您可以 测试 使用 instanceof
关键字:
public Integer test(T m)
{
if(m instanceof MessageA || m instanceof MessageB) {
System.out.println( "A subclass of Message instance." );
//your custom process
}else{
System.out.println( "A Message instance." );
//your custom process
}
}
编辑
由于泛型在 Java 中的实现方式,您无法找出泛型 class 在运行时使用的对象类型(泛型类型 T 在运行时不保留) ). 仍然,您可以使用私有数据成员并在每个 Message 分支中重载您的测试方法 并在通用 Class 中使用它:
public class MyClass<T extends Message>
{
private Class<T> type;
public MyClass(Class<T> type) { this.type = type; }
public Integer test(T m)
{
return type.test(m);
}
}
我的回答可能听起来很刺耳,但你的设计似乎有点破烂。
最简单的解决方案是从一个公共的 class 派生 MessageA 和 MessageB(这可能与您的界面无关),并向此 class 添加一个受保护的函数,您可以称呼。
或者您创建第二个界面,然后回答以下问题之一。
请参阅以下 SO 问题之一:
Generic extending class AND implements interface
Java generics - Make Generic to extends 2 interfaces