Getting error: incompatible types: int cannot be converted to T.
I want to build a queue using linked list that can store items of different data types. Please suggest ways on how can i pass values belonging to different data types into the generic function add().
public void main(String args[])
{
MyQueue<T> q=new MyQueue<T>();
q.add(10);
q.add("Hello");
}
public void add(T item)
{
QueueNode<T> t=new QueueNode<T>(item);
if(last!=null)
{
last.next=t;
}
last=t;
}
T is a placeholder for a Type, but you can't declare T like this since T must be a known type. You want something like this. Here T is a known type which is passed to QueueNode and MyQueue.
package com.company;
import java.util.ArrayList;
import java.util.List;
class QueueNode<T> {
private T nodeVal;
T getNodeVal() {
return nodeVal;
}
void setNodeVal(T nodeVal) {
this.nodeVal = nodeVal;
}
QueueNode(T nodeVal) {
this.nodeVal = nodeVal;
}
}
class MyQueue<T> {
private List<QueueNode<T>> actualQueue = new ArrayList<QueueNode<T>>();
public List<QueueNode<T>> getActualQueue() {
return actualQueue;
}
public void enqueue(T t) {
actualQueue.add(new QueueNode<>(t));
}
public QueueNode<T> dequeue() {
return actualQueue.remove(0);
}
}
class Main {
public static void main(String[] args) {
MyQueue<Integer> integerQueue = new MyQueue<Integer>();
integerQueue.enqueue(1);
integerQueue.enqueue(2);
integerQueue.enqueue(3);
integerQueue.getActualQueue().forEach(e -> System.out.print(e.getNodeVal() + " ")); //prints 1 2 3
System.out.println();
integerQueue.dequeue();
integerQueue.getActualQueue().forEach(e -> System.out.print(e.getNodeVal() + " ")); //prints 2 3
System.out.println();
integerQueue.dequeue();
integerQueue.getActualQueue().forEach(e -> System.out.print(e.getNodeVal() + " ")); //prints 3
System.out.println();
}
}
You should change de T for Object. This way you can place whatever data type you want and then you can use a foreach, for example:
public static void main(String args[])
{
Queue<Object> queues=new LinkedList<>();
queues.add(10);
queues.add("Hello");
for(Object queue:queues){
System.out.println(queue);
}
}
The Generic class gives solution more bigger.
Also consider that int is a primitive data type and it's not a class. In this case Integer is the class that uses int.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Let's say I have a class,
public class Dummy {
public List<Integer> foo() {...}
public Abc<Integer> bar() {...}
}
For method foo, I can check the return type using ParameterizedType, but for method bar, is there a way to know if Ab<Integer> is actually a List<Integer>?
Edit to add some background:
We have dozens of 3rd party POJO classes, and we need to extract the field information of these classes, and create a schema based on it.
For the regular primitive fields, it's straight forward, but in those classes, they also have field with type like List<Integer>, or ArrayList<Integer>, or Abc<Integer> (Abc<T> may or may not implements List<T>).
So we need a way to determine if it's a repeated field or not, if it's a repeated one, what is the type argument, is it an Integer or some other things?
You can use Class.isAssignableFrom to determine whether a particular class IS-A another class, and you can look at the type arguments given to the return type:
public class App {
static class AbcWhichIsAList<E> extends ArrayList<E> {
}
static class AbcWhichIsNotAList<E> {
}
public List<Integer> foo() { return null; }
public AbcWhichIsAList<Integer> bar() { return null; }
public AbcWhichIsNotAList<Integer> baz() { return null; }
public AbcWhichIsAList<String> xyzzy() { return null; }
public static boolean returnsList(Class clazz, String methodName) throws NoSuchMethodException {
Method m = clazz.getMethod(methodName);
return List.class.isAssignableFrom(m.getReturnType());
}
public static boolean returnsIntegerList(Class clazz, String methodName) throws NoSuchMethodException {
Method m = clazz.getMethod(methodName);
Type returnType = m.getGenericReturnType();
if (returnType instanceof ParameterizedType parameterisedReturnType) {
return List.class.isAssignableFrom(m.getReturnType()) &&
parameterisedReturnType.getActualTypeArguments()[0].getTypeName().equals(Integer.class.getTypeName());
} else {
return false;
}
}
public static void main(String[] args) throws NoSuchMethodException {
for (String s: Arrays.asList("foo", "bar", "baz", "xyzzy") ){
System.out.println(s + ": " + returnsIntegerList(App.class, s));
}
}
}
The above code assumes that the methods of interest take no parameters.
I feel that there should be a better way of comparing the type parameters than comparing the names of the types.
It's possible to handle more complicated cases. I don't have time to write a full solution, but the code below does half the job: It traverses the inheritance hierarchy until it finds List. However it does not keep track of the actual type parameters on the way.
package org.example;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class App {
static class AbcWhichIsAList<E> extends ArrayList<E> {}
static class AList extends AbcWhichIsAList<Integer> {}
static class AbcWhichIsNotAList<E> {}
public List<Integer> foo() { return null; }
public AbcWhichIsAList<Integer> bar() { return null; }
public AbcWhichIsNotAList<Integer> baz() { return null; }
public AbcWhichIsAList<String> xyzzy() { return null; }
public AList blech() { return null; }
public static boolean returnsIntegerList(Class clazz, String methodName) throws NoSuchMethodException {
Method m = clazz.getMethod(methodName);
Type returnType = findListType(m.getGenericReturnType());
if (returnType != null && returnType instanceof ParameterizedType parameterisedReturnType) {
return List.class.isAssignableFrom(m.getReturnType()) &&
parameterisedReturnType.getActualTypeArguments()[0].getTypeName().equals(Integer.class.getTypeName());
} else {
return false;
}
}
private static Type findListType(Type type) {
if (type.getTypeName().startsWith("java.util.List")) {
return type;
}
Type listType = null;
if (type instanceof ParameterizedType parameterizedType) {
listType = findListType(parameterizedType.getRawType());
}
if (type instanceof Class clazz) {
if (clazz.getGenericSuperclass() != null) {
listType = findListType(clazz.getGenericSuperclass());
}
if (listType == null) {
for (Type t : clazz.getGenericInterfaces()) {
listType = findListType(t);
if (listType != null)
break;
}
}
}
return listType;
}
public static void main(String[] args) throws NoSuchMethodException {
for (String s: Arrays.asList("foo", "bar", "baz", "xyzzy", "blech") ){
System.out.println(s + ": " + returnsIntegerList(App.class, s));
}
}
}
Read about the object.instanceof(someType) method, it might be what you are looking for.
The java instanceof operator is used to test whether the object is an instance of the specified type (class or subclass or interface).
If not - the typeof method is worth trying as well.
I have code like
public class Functionz {
public static boolean test() {
return true;
}
public static void main(String[] args) {
Function[] funcs = new Function[] {test}; // and others
for (Function func : funcs) {
func();
}
}
}
and my error is: cannot find symbol: test in the line with the function array declaration.
Hope this isn't a stupid question, very new to java, not new to object oriented languages like python and C++.
A Function in Java does takes one parameter as input and one as output.
You might declare parameter's type this way : Function<Integer, String> is a function that transforms an Integer into a String
Your method test() does not take any input value and outputs a boolean so it's a Supplier.
import java.util.function.Supplier;
public class Main {
public static boolean test() {
System.out.println("lorem ipsum");
return true;
}
public static void main(String[] args) {
Supplier[] funcs = new Supplier[] {Main::test}; // and others
for (Supplier func : funcs) {
func.get();
}
}
}
Your code would compile if test requires one (and only one parameter) like
import java.util.function.Function;
public class Main {
public static boolean test(String str) {
System.out.println(str);
return true;
}
public static void main(String[] args) {
Function[] funcs = new Function[] {(Object anyObject) -> test(anyObject.toString())}; // and others
for (Function func : funcs) {
func.apply("lorem ipsum");
}
}
}
Here's the list of those types
Please note that Function doesn't type its parameters in construction because you can't create arrays with generic type in Java (you might for specific usecases) => Use a List will help you here
I was learning Java templates. As generics are compiled, I was hoping runtime deduction of type and hence invocation accordingly.
Seems it doesn't. i.e. deduction is based on compile time type deduction, although template itself is compiled.
Test Interface:
interface op {
public Object Do(Object o);
public Class getClass1();
public Object getTest();
}
Interface implementation
class intop implements op{
public Object Do(Object o) {
return (Integer) o;
}
public Class getClass1() {
return Integer.class;
}
public Object getTest() {
return new Integer(1);
}
}
class strop implements op{
public Object Do(Object o) {
return (String) o;
}
public Class getClass1() {
return String.class;
}
public Object getTest() {
return "Test";
}
}
Template & Specilizations
class Utils {
public static void performOp(Integer i) {
System.out.println("Interger Object :" + i);
}
public static void performOp(String s) {
System.out.println("String object : " + s);
}
public static <T> void performOp(T o) {
System.out.println("Generic Object :" + o.toString());
}
}
Testing
public class GenMethod {
public static void main(String args[]) {
Utils.performOp(1);
Utils.performOp("Test");
Utils u = new Utils();
Integer i = 4;
Object o = i;
ArrayList<op> a = new ArrayList<op>();
a.add(new intop());
a.add(new strop());
Random rn = new Random();
op b = a.get(rn.nextInt(2));
Utils.performOp(b.getClass1().cast(b.getTest()));
Utils.performOp(u);
}
}
I was Expecting output to be something like:
Interger Object :1
String object : Test
Interger Object :1
Generic Object :Utils#64c3c749
But It was :
Interger Object :1
String object : Test
Generic Object :1
Generic Object :Utils#3ce53108
Is there a way to correctly do specialized template method invocation based on runtime type deduction?
PS : I want to avoid the 'instanceof' & 'if..else' ladders as much as possible.
I am currently trying to learn how to use Generics from a book. In this chapter it says to take a piece of data T and convert it to an integer. I am trying different things in Eclipse, but none of them seem to allow this. How could you perform the following task:
LinkedList<T> arr = new LinkedList<T>();
Float fl = 8.74273123948;
arr.add(fl);
Then in another class:
public int findValue(Node node)
{
T data = node.data;
int value = Number.valueOf(data);
return value;
}
I have tried using .valueOf() and (int) among a few other things and nothing seems to satiate Java. The book insists on keeping the method generic in case floats or doubles were used instead of strings or ints.
EDIT: For other people that might have a similar question. Gleaned from all the comments to this question and the answer that was accepted:
use the .toString() on the data and then parse it as you need to whichever data type you need.
Hmm, that is an odd book. I'll try to tell you the gist of it based on what I know.
Generics are a construct that allow you compile-time check of whether a type you are trying to use in a specific collection, method, or class is actually something that knows the functionality that is necessary for that specific thing to function.
For example, you need to use the function determined by the interface called SearchParameter in your template, but you only see the <T> parameter as an object. Or maybe a better example in your case would be a custom interface called IntegerConvert like so:
public interface IntegerConvert
{
Integer returnAsInteger();
}
And you could have a class like this:
public class MyData implements IntegerConvert
{
private String data;
public MyData(String data)
{
this.data = data;
}
#Override
public Integer returnAsInteger()
{
return Integer.parseInt(data); //throws ParseException if it doesn't work
}
}
And then you could have a List of these like this:
List<IntegerConvert> listOfConvertibles = new ArrayList<IntegerConvert>();
or if you want to go a bit more generic for the future,
List<? extends IntegerConvert> listOfConvertibles = new ArrayList<IntegerConvert>();
and then you can do
listOfConvertibles.add("25");
listOfConvertibles.add("40");
listOfConvertibles.add("35");
for(IntegerConvert ic : listOfConvertibles)
{
System.out.println("" + ic.returnAsInteger());
}
Although that was a bit of an overcomplicated example, I guess. A simpler example would be the following:
public class Node<E>
{
private E data;
public Node(E e)
{
this.data = e;
}
public E getData()
{
return data;
}
public void setData(E e)
{
data = e;
}
public void print()
{
System.out.println(data.toString());
}
}
public class MyClass
{
public void doSomething()
{
List<Node<Float>> listOfFloatNodes = new ArrayList<Node<Float>>();
listOfFloatNodes.add(new Node<Float>(new Float(8.7472742f)));
listOfFloatNodes.add(new Node<Float>(new Float(5.56842742f)));
listOfFloatNodes.add(new Node<Float>(new Float(6.5467742f)));
MyOtherClass moc = new MyOtherClass();
moc.useNodeList(listOfFloatNodes);
}
}
public class MyOtherClass
{
public <E> void useNodeList(List<Node<E>> list)
{
for(Node<E> node : list)
{
printNode(node);
}
}
public <E> void printNode(Node<E> node)
{
node.print();
}
}
public class MainClass
{
public static void main(String[] args)
{
MyClass myClass = new MyClass();
myClass.doSomething();
}
}
If you have any questions, comment.
try to observe below examples:
public static void main(String[] args) {
test0("13");
test0(new Integer(13));
test1();
System.out.println(findValue(new Node("10")));
}
private static <T> void test0(T a) {
LinkedList<T> arr = new LinkedList<T>();
arr.add((T) a);
System.out.println(arr.getFirst());
}
private static <T> void test1() {
LinkedList<T> arr = new LinkedList<T>();
arr.add((T) new Integer(13));
System.out.println(arr.getFirst());
}
public static <T> int findValue(Node node) {
T data = (T) node.data;
int value = Integer.valueOf(data.toString());
return value;
}
where Node is :
public class Node {
//this should be private
public String data;
public Node(String data) {
this.data = data;
}
//use getter below to access private data
public String getData() {
return data;
}
}
all this is possible because, unchecked casts from a known type to T is allowed (of course with warnings) and compiler believes you for the casting.
Answer not entirely on the topic albeit closely related. I had a problem and didn't find the answer. Then I found solution and thought I'd share:
I was trying to cast generic value to primitive type:
<TYPE> boolean equal(TYPE val, Class<?> type) {
if (float.class == type) {
float val2 = (float) val; // incompatible types: TYPE cannot be converted to float
float val3 = (float) (Object) val; // works
...
Long story short: first version doesn't work and the second does. Quite annoying.
I wanted to create a static method which prints the contents of an array.I wrote one for String[] as below
public static void print(String[] a){
for(String x : a){
System.out.print(x+", ");
}
System.out.println();
}
I thought I could create a method which takes in a generic type ,and modified the code as below
public class ArrayPrinting<E> {
public static void printArray(E[] a){
for(E x : a){
System.out.print(x+", ");
}
System.out.println();
}
public static void main(String[] args) {
String[] a = {"A","B","C","D","E"};
}
}
But,this gives a compiler error
'Cannot make a static reference to the non-static type E'
So,how do I create such a method?or is it impossible ? Since this is a static method, I wonder how I can invoke the method without creating an instance. A call like
ArrayPrinting<E>.printArray(a) doesn't look right ..
Can someone help?
Try this
public class ArrayPrinting {
public static <E> void printArray(E[] a){
for(E x : a){
System.out.print(x+", ");
}
System.out.println();
}
public static void main(String[] args) {
String[] a = {"A","B","C","D","E"};
ArrayPrinting.printArray(a);
}
}
Ravi already covered the proper syntax for a generic method. I just want to point out that this particular method doesn't need to be generic:
public static void printArray(Object[] a) {
for (Object x : a) {
System.out.print(x + ", ");
}
System.out.println();
}
The reason this works is array covariance - a String[] is an Object[].
Class's generic type parameters are for class level variables and methods (instance variables and methods).So you can't use it.
You can handle it by declaring type parameter in the method itself:
public static <E> void printArray(E[] a){
.............
}
public class ArrayPrinting<E> {
public void printArray(E[] a){
for(E x : a){
System.out.print(x+", ");
}
System.out.println();
}
public static void main(String[] args) {
String[] a = {"A","B","C","D","E"};
new ArrayPrinting().printArray(a);
}
}