Java Generics Silly Thing (Why cant I infer the type?)

我怕爱的太早我们不能终老 提交于 2019-12-12 13:34:49

问题


I´ll try to be short as the question has not been very answered. For the long explanation, go after this briefing.

I will show what Im trying to do. Something like this (infering the incoming type from the constructor in order to use it in another method getLeaderHerd as a return type)... :

public class ZooCage{

    private CageFamily<T> inhabitants;  

    public <T>ZooCage(CageFamily<T> herd) {
        this.inhabitants=herd;      
    }

    public T getHerdLeader() {
        return inhabitants.getLeader();
    }   
}

or this

public class ZooCage{

    private (Type) T;   

    public ZooCage(CageFamily<T> herd) {
        this.T=T;       
    }

    public T getHerdLeader() {
        return inhabitants.getLeader();
    }   
}

so I could call from Main something like:

ZooCage cage = new ZooCage(new CageFamily<Lion>()); //Imagine new CageFamily its not empty
Lion leader = cage.getHerdLeader();

Even if its not possible, why should I think that that is not reasonable to feature? Its type safe if the compiler is intelligent and less redundant that typifiing the class ZooCage which is not necessary

I,m assessing using Generics for a particular behavior. I managed to get it work but I don,t understand why cant I infer the type from the arg. So I created this example which runs ok without warnings with the purpose of simplifying the actual architecture.

( Look directly the last 2-lines snippet for a fast briefing )

Suppose I got these two classes. The target one:

package Zoo;
import Zoo.Main.CageFamily;
import Zoo.Main.Vertebrate;

public class ZooCage<T extends Vertebrate>{

    private CageFamily<T> inhabitants;  

    public ZooCage(CageFamily<T> herd) {
        this.inhabitants=herd;      
    }

    public T getHerdLeader() {
        return inhabitants.getLeader();
    }   
}

Imagine that in cages there can only be Vertebrates (Insects/aracnids are not to big ang giant quids/octopus needs aquatic medium)

The other one class, Main.java

package Zoo;
import java.util.ArrayList;

public class Main {

    public static void main(String[] args){
        new Main().test();
    }

    public void test(){
        CageFamily<Lion> lionsHerd = new CageFamily<Lion>();
        lionsHerd.add(new Lion("Simba"));
        lionsHerd.add(new Lion("Nala"));

        CageFamily<Bear> bearsHerd = new CageFamily<Bear>();
        bearsHerd.add(new Bear("Yogi"));
        bearsHerd.add(new Bear("Boo-boo"));

        ZooCage<Lion> cageLions = new ZooCage<Lion>(lionsHerd);     
        ZooCage<Bear> cageBears = new ZooCage<Bear>(bearsHerd);

        for (ZooCage<?> cage : new ZooCage[]{cageLions,cageBears} ) 
           System.out.println("The leader is "+ cage.getHerdLeader());

    }

    public interface Vertebrate{
        public String toString();
        public int numBones();
    }
    public class Lion implements Vertebrate{
        private String name;
        public Lion (String name){this.name=name;}
        public String toString(){return name + " (who has "+numBones()+" bones)";}
        public int numBones(){return 345;}
    }
    public class Bear implements Vertebrate{
        private String name;
        public Bear (String name){this.name=name;}      
        public String toString(){return name + " (who has "+numBones()+" bones)";}
        public int numBones(){return 658;}
    }
    public class CageFamily<E extends Vertebrate> extends ArrayList<E>{
        final static long serialVersionUID = 1L;
        public E getLeader(){
             return get(0); //Let,s assume the first added is the leader
        }
    }
}

This compiles OK and prints

The leader is Simba (who has bones)
The leader is Yogi (who has bones)

What Im wondering is: Is there any way (only using types/generics and without supressingWarnings nor castings) to avoid the typification of the class ZooCage as a whole? I tried thousand ways to get the inference of the type from ZooCage,s constructor arg to the return value for getHerdLeader. It should be not necessary typifying ZooCage when his constructor comes with the expected type. Seems redundant and makes you having to know beforehand the type!

Thank you very much to all who can help!


回答1:


Java 7 lets you do ZooCage<Type> = new ZooCage<>(argument). That feature is new in Java 7, though, and isn't available in earlier versions of Java.

Alternately, a traditional way of getting around Java 6's lack of type inference is to write a factory method

public static <T> ZooCage<T> newZooCage() {
  return new ZooCage<T>();
}

and then newZooCage() gets its type automatically inferred, since even Java 5 had type inference for methods -- just not for constructors.




回答2:


Java does not support type inference.

If your interested in that you should look at Scala.

In Java 7 you can ommit the type between < > on the right hand side. In Java 6 you can do it with static methods with Guava. Java 8 may/will have literals (or at least last time a checked) so that might help also.

I don't agree that any of these are true type inference (see comments below).



来源:https://stackoverflow.com/questions/10290218/java-generics-silly-thing-why-cant-i-infer-the-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!