I have a Node<T> (inner) class in Graph<T> class:
public class Graph<T> {
private ArrayList<Node<T>> vertices;
public boolean addVertex(Node<T> n) {
this.vertices.add(n);
return true;
}
private class Node<T> {...}
}
When I run this:
Graph<Integer> g = new Graph<Integer>();
Node<Integer> n0 = new Node<>(0);
g.addVertex(n0);
The last line give me error:
The method addVertice(Graph<Integer>.Node<Integer>) in the type Graph<Integer> is not applicable for the arguments (Graph<T>.Node<Integer>)
Why? Thanks in advance?
Your inner class should not override T Since T is already used in outerclass. Consider what can happen if it was allowed. Your outer class would have referred to Integer and Inner class would have referred to another class that too for the same instance.
public boolean addEdge(Node node1, Node node2) {
return false;
}
Graph<Integer> g = new Graph<Integer>();
Graph<Integer>.Node n0 = g.new Node(0);// As T happens to be integer you can use inside node class also.
public class Node {
T t;
Node(T t) {
}
}
Or you can use Static Inner class since Static Generics Types are different than instance generic types.
For More Explanation you can Refer to JLS # 4.8. Raw Types
Following code works fine for me. Running on JRE 1.6
public class Generic<T> {
private ArrayList<Node<T>> vertices = new ArrayList<Node<T>>();
public boolean addVertice(Node<T> n) {
this.vertices.add(n);
System.out.println("added");
return true;
}
public static class Node<T> {
}
public static void main(String[] args) {
Generic<Integer> g = new Generic<Integer>();
Node<Integer> n0 = new Node<Integer>();
g.addVertice(n0);
}
}
Related
I was reading following paper about solving Expression Problem using Java Generics.
http://www.daimi.au.dk/~madst/ecoop04/main.pdf
The author propose the first solution using the F-Bounded types to ensure left and right parameters are of type EvalExp.
I tried to solve the problem without using the F-Bounded type and ended up with following code which seems to work
public interface Exp {
void print();
}
public class Lit implements Exp {
public int value;
Lit(int value) { this.value = value; }
public void print() { System.out.print(value); }
}
public class Add<C extends Exp> implements Exp {
public C left, right;
public Add(final C left, final C right) {
this.left = left;
this.right = right;
}
#Override
public void print() {
left.print(); System.out.print("+"); right.print();
}
}
public interface EvalExp extends Exp {
int eval();
}
public class EvalLit extends Lit implements EvalExp {
public EvalLit(int value) { super(value); }
#Override
public int eval() { return value; }
}
public class EvalAdd<A extends EvalExp> extends Add<A> implements EvalExp {
public EvalAdd(A left, A right) {
super(left, right);
}
#Override
public int eval() {
return left.eval() + right.eval();
}
}
Does this solution solve the Expression Problem (will it be extensible for new data and operations)?
Does is satisfy code level extensibility (see the papers for details).
Does above solution has any disadvantages over the F-Bounded solution proposed in the paper?
Any explanation is welcome.
Edit: Updated the code to fix the compilation issue.
I'm java virgin. I've made really simple code like below.
class TreeData implements Comparable<TreeData> {
private String sixString;
private ArrayList<Integer> stringNum = new ArrayList<Integer>();
private ArrayList<Integer> charNum = new ArrayList<Integer>();
public TreeData(String sixString, int stringNum, int charNum){
this.sixString = sixString;
(this.stringNum).add(stringNum);
(this.charNum).add(charNum);
}
public int compareTo(TreeData other) {
return sixString.compareTo(other.getSixString());
}
public String getSixString(){
return sixString;
}
}
class Child<T extends Comparable<T>>{
public void print(T data){
//error : String a = data.getSixString();
System.out.println("hi");
}
}
public class Test {
public static void main(String[] args) {
Child<TreeData> child = new Child<TreeData>();
TreeData td = new TreeData("sixString", 8, 2);
child.print(td);
}
}
I had a problem in 'print' method in the Child class. When I tried calling the getSixString() method of data(passed as argument), it occurs error. I don't know why I can't using public method in the argument 'data'. Is it related with Generic? Thanks, in advance.
In your Child class, you only define T to be extending Comparable. Yet you expect it to have the method getSixString which Comparable doesn't have. What you probably want it for it to be extending TreeData:
class Child<T extends TreeData>{
public void print(T data){
String a = data.getSixString();
//should work now since T defines getSixString()
}
}
Or better yet if all you want is for T to be TreeData, you don't need any generic class. I'm assuming your real intention was:
class Child extends TreeData {
public void print(){
String a = getSixString();
}
}
Situation
I am making a graph class that looks like this:
class ImmutableGraph<G> {
Node<G> selectedNode;
private ImmutableGraph(Node<G> initialNode) { selectedNode = initialNode; }
//many more things
}
and I'm currently using a (nested) builder class like so
public static class GraphBuilder<B> {
Node<B> currentNode;
public GraphBuilder(B value){ currentNode = new Node(value); }
public ImmutableGraph<B> build(){
return new ImmutableGraph<B>(currentNode);
}
//many more things
}
which uses the (nested) node class
private static class Node<N> {
private final N value;
Array<Nodes<N>> neighbours;
public Node(N v){ value = v; }
//many more things
}
Problem
I can't find a way to instantiate my ImmutableGraph using my builder because the return type is not correct. Indeed, compilation suggests that GraphBuilder.build() should return a type ImmutableGraph<Node<B>> and not ImmutableGraph<B>
For now the only solution I found is to change the return type to ImmutableGraph<Node<B>> but that's feels dumb since all graphs (except empty ones) are graphs of nodes. The Node type is also confusing since the user never interacts with it.
edit:
corrected the "new" in the factory method of the builder
I think that your build method should return new ImmutableGraph<B>(currentNode);
import java.util.List;
public class ImmutableGraph<G> {
Node<G> selectedNode;
private ImmutableGraph(Node<G> initialNode) {
selectedNode = initialNode;
}
// many more things
public static class GraphBuilder<B> {
Node<B> currentNode;
public GraphBuilder(B value) {
currentNode = new Node<B>(value);
}
public ImmutableGraph<B> build() {
return new ImmutableGraph<B>(currentNode);
}
// many more things
}
private static class Node<N> {
private final N value;
List<Node<N>> neighbours;
public Node(N v) {
value = v;
}
// many more things
}
public static void main(String[] args) {
GraphBuilder<Integer> builder = new GraphBuilder<Integer>(Integer.MAX_VALUE);
ImmutableGraph<Integer> graph = builder.build();
System.out.println(graph.selectedNode.value);
}
}
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.
public class INode
{
private int value;
private INode right, down;
private int row, col;
public INode(int value)
{
this.value = value;
}
public int getValue()
{
return value;
}
public void setValue(int value)
{
this.value = value;
}
public INode getRight()
{
return right;
}
public void setRight(INode right)
{
this.right = right;
}
public INode getDown()
{
return down;
}
public void setDown(INode down)
{
this.down = down;
}
public int getRow()
{
return row;
}
public void setRow(int row)
{
this.row = row;
}
public int getCol()
{
return col;
}
public void setCol(int col)
{
this.col = col;
}
}
I can get value of a = 8 but for head, even though I use constructor to set up, still give me value = null... dont know why.
And the driver is:
import java.util.*;
public class List
{
public static INode head;
public List()
{
head = new INode(8);
}
public static void main (String[] args)
{
INode a = new INode(8);
int data = a.getValue();
System.out.println(data);
System.out.println(head.getValue());
}
}
Please help me a hand guys. Dont understand why when I use a constructor, I cant assign the value to the node, yet when I create an instance, i can...
Thank guys, love you folks! Great help!
You do not instantiate the class List. Change your code to
public INode head; // remove static
public List() {
head = new INode(8);
}
And modify your main method:
public static void main (String[] args) {
INode a = new INode(8);
int data = a.getValue();
System.out.println(data);
List l = new List(); // create new List instance
System.out.println(l.head.getValue()); // get the head from List instance
}
Another valid alternative would be to change just one line:
public static INode head = new INode(8); // create instance during class initialization
I recommend to look at the difference between class (static) and instance variables, e.g. in the Java Tutorials (extract follows):
Instance Variables (Non-Static Fields) Technically speaking, objects store their individual states in "non-static fields", that is,
fields declared without the static keyword. Non-static fields are also
known as instance variables because their values are unique to each
instance of a class (to each object, in other words); the currentSpeed
of one bicycle is independent from the currentSpeed of another.
Class Variables (Static Fields) A class variable is any field declared with the static modifier; this tells the compiler that there
is exactly one copy of this variable in existence, regardless of how
many times the class has been instantiated. A field defining the
number of gears for a particular kind of bicycle could be marked as
static since conceptually the same number of gears will apply to all
instances. The code static int numGears = 6; would create such a
static field. Additionally, the keyword final could be added to
indicate that the number of gears will never change.
You have to initialize List object in main method
public static void main (String[] args)
{
new List();
INode a = new INode(8);
int data = a.getValue();
System.out.println(data);
System.out.println(head.getValue());
}
You should initialize your static variables either at the point of declaration, or in a static initializer block. And not in a constructor.
Constructor will only be used, when you instantiate your List class, that you are not doing anywhere. static initializer block is executed, when the class is loaded into memoty. So, your INode will get initialized when the class is loaded.
public static INode head;
static {
head = new INode(8);
}
or just: -
public static INode head = new INode(8);
static variables are common to all instances. If a change is made
for one instance, it will be reflected in all the instances. So be
sure before using them, that you actually want that. If possible,
declare your INode as non-static variable. And instantiate your
List class before using it.
public INode head = new INode(8);
And then in your main method, you can access it like this: -
List list = new List();
System.out.println(list.head.getValue());
You can do this either way .. either you can create an instance of Class List or
you can initialize head to point to object of INode.
This depends on the business logic that you require
public static void main(String[] args) {
INode a = new INode(8);
int data = a.getValue();
System.out.println(data);
List list = new List();
System.out.println(list.head.getValue());
head = new INode(6);
System.out.println(head.getValue());
}