简体   繁体   中英

Cannot infer type arguments for Generic Class

I am trying to create Expression Tree using the Postfix Expression. This needs a Stack which could hold Tree Objects. I created a generic Stack class which could except <TreeTemp> as type argument.

On trying to initialize the stack with following statement, its giving "Cannot infer type arguments for TreeStack<>" error. private TreeStack<TreeTemp> stack1 = new TreeStack<>(new TreeTemp()); Stack Class:

public class TreeStack<T> {

    private T [] stackElem;
    private final int MAXSTACKSIZE;
    private int top;
    
    public TreeStack(Class<T> t) {
        top = -1;
        MAXSTACKSIZE = 20;
        final T[] stackElem = (T[]) Array.newInstance(t, MAXSTACKSIZE);
        this.stackElem = stackElem;
        
    }
    
    public void push(T elem) throws Exception{
        if(isFull()) {
            stackElem[++top] = elem;
        }
        else
            throw new Exception("Stack is already Full");
    }
    
    public T pop() throws Exception {
        
        if(isEmpty()) {
            return stackElem[top--];
        }
        else
            
            throw new Exception("Stack is Empty");
    }
    
    public boolean isEmpty() {return top == -1;}
    
    public boolean isFull() {return top==MAXSTACKSIZE-1;}
}

Postfix.class(Class having method for creating tree)

public class PostFix {

    private String expression = new String("A*B+C");
    private char [] expElem = expression.toCharArray();
/*Error on below Statement*/

    private TreeStack<TreeTemp> stack1 = new TreeStack<>(new TreeTemp());
    
    public TreeTemp makeTree() throws Throwable {
        try {
        for(int i=0;i<expElem.length;i++) {
            ExpNode eNode = new ExpNode();
            eNode.setiData(expElem[i]);
            TreeTemp t = new TreeTemp();
            t.setRoot(eNode);
            if(!Character.isLetter(expElem[i])) {
                t.setLeftTree(stack1.pop());
                t.setRightTree(stack1.pop());   
                }
            stack1.push(t);
        }
        return stack1.pop();
        }catch (Exception e) {
            throw new Exception("Stack Error while creating a Tree", e);
        }
    }
    
    public static void main(String[] args) throws Throwable {
        PostFix pf = new PostFix();
        TreeTemp t = pf.makeTree();
        
        
    }

Tree Class(Type which i want to add into Stack):

public class TreeTemp {
    
    private ExpNode root;
    private TreeTemp leftTree;
    private TreeTemp rightTree;
    
    /*public TreeTemp(ExpNode expNode) {
        root = expNode;

        }*/

    public TreeTemp getLeftTree() {
        return leftTree;
    }

    public void setLeftTree(TreeTemp leftTree) {
        this.leftTree = leftTree;
    }

    public TreeTemp getRightTree() {
        return rightTree;
    }

    public void setRightTree(TreeTemp rightTree) {
        this.rightTree = rightTree;
    }

    public ExpNode getRoot() {
        return root;
    }
    public void setRoot(ExpNode node) {
        this.root = node;
    }
}

Can someone pls give some pointers.

Your TreeStack has only one constructor. Here it is:

public TreeStack(Class<T> t) {

Thus, to invoke it, you need to pass the class object that represents the class associated with the T type. So, the class itself, not 'some particular instance of T'. When you call it on your error line:

private TreeStack<TreeTemp> stack1 = new TreeStack<>(new TreeTemp());

You are passing an instance of TreeTemp. Not the concept 'TreeTemp, the class'. Try new TreeStack<>(TreeTemp.class);

Note that as a general rule, passing a Class<T> is a code smell; you're trying to make generics something that it isn't (you're trying to runtime reify). This is objectively bad: It means you can't make a TreeStack<List<String>> , for example, because you're restricted to the overlap where both generics as well as jlClass instances can represent the thing, and that's just simple, non-genericsed, non-primitive classes.

final T[] stackElem = (T[]) Array.newInstance(t, MAXSTACKSIZE);

Looks like the only reason you want that class is to make sure your array is properly typed.

This is not neccessary. Just make a new Object[] array, and cast to T anytime you need to return a T. Now your TreeStack constructor needs no arguments at all.

Check the source of java.util.ArrayList, which agrees with this assessment; it is backed by an Object array, not a T[].

The TreeStack constructor accepts a Class<T> , not a T , so you should do:

new TreeStack<>(TreeTemp.class);

Since this is an exercise to create expression trees, you don't really need to implement stacks from scratch. You should just use the ArrayDeque class through the Deque interface in the Java Collections API.

private Deque<TreeTemp> stack1 = new ArrayDeque<>();

Deque has all the methods your TreeStack has, and many more.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM