Java:如果实现T(Base)和其他任何其他实现的“Base”,那么做一些事情

时间:2016-01-25 10:11:06

标签: java generics type-erasure

我有一个界面Message,其中有两个实现MessageAMessageB

现在我有以下泛型类,它采用扩展T的类型变量Message。如果参数是test(或子类型),我希望方法T以一种方式操作,如果参数是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);                                
    }                                                 
}                                                     

我可以进行明确的类型检查,但我想有一种更清洁的方式来实现我的目标。

修改

我更喜欢使用覆盖或重载,因为在我的项目中,我将有一个类MyClassA implements MyClass<MessageA>来实现方法test(MessageA m)。但我想在基础泛型类中实现“错误”的情况。

以下工作:

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;                           
        }                                       
    }                                           
}                                               

但它迫使我在我的通用if-then的每个实例中都使用print("bad type")实现MyClass<T extends Message>块(为了代码重复)。

修改 根据公认的解决方案,我发布了一个功能齐全的minimal example here

3 个答案:

答案 0 :(得分:0)

重载是静态的。它使用编译时对象类型而不是实际的运行时类型。使用Message#test()来覆盖或向代码添加显式类型检查(即instanceof)。

答案 1 :(得分:0)

您可以使用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中实现泛型的方式,您无法找到泛型类在运行时使用的Object类型(泛型类型T不在运行时保留)。 仍然可以使用私有数据成员并在每个Message分支中重载您的测试方法并在泛型类中使用它:

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);                               
    }   

}

答案 2 :(得分:0)

我的回答可能听起来很刺耳,但你的设计似乎有点破碎。

最简单的解决方案是从公共类(可能与您的接口无关)派生MessageA和MessageB,并向您可以调用的此类添加受保护的函数。

或者您创建了第二个界面,并按照以下问题之一进行操作。

请参阅以下SO问题之一:

Generic extending class AND implements interface

Java generics - Make Generic to extends 2 interfaces