I have an abstract generic class which requires a numeric constant to initialize an array. I know the size of array at compile time when I use that generic class. Is there any way to implement this?
abstract class Node<T, MagicN> {
private T parent = null;
private T[] child = (T[]) new Object[MagicN];
//some methods that rely on the initialized array.
}
final class ConcreteNode extends Node<ConcreteNodeType, 2> {
}
The class ConcreteNode has 2 children in this example.
You can't use a Generic as a template. As Java's code optimisation is done at runtime, there is little reason to have such compile time inlining.
abstract class Node<T extends Node> {
private final T parent;
private final T[] child;
Node(T parent, int size) {
this.parent = parent;
child = (T[]) new Object[size];
}
//some methods that rely on the initialized array.
}
final class ConcreteNode extends Node<ConcreteNode> {
ConcreteNode(ConcreteNode parent) {
super(parent, 2);
}
}
You can't have values instead of a generic type (or you should have to create a class for each value you may use...)
I think the best in your case would to have a constructor that takes this value as a parameter for example :
abstract class Node<T> {
private T parent = null;
private int MagicN = 0;
private T[] child = null;
protected Node(int MagicN)
{
this.MagicN = MagicN;
this.child = (T[]) new Object[MagicN];
}
//some methods that rely on the initialized array.
}
final class ConcreteNode extends Node<ConcreteNodeType> {
public ConcreteNode()
{
super(2);
}
}
In terms of performance, there is no difference between what you are trying to do and this example since your child array is initialized in an object context and not a static one.
Why not do it this way?
abstract class Node<T> {
private T parent = null;
private T[] child;
public Node(int childCount) {
child = (T[]) new Object[childCount];
//some methods that rely on the initialized array.
}
final class ConcreteNode extends Node<ConcreteNodeType> {
public ConcreteNode()
{
super(2);
}
}
Related
I have following class:
class TreeItem<T extends TreeItem<?>>{
private final ObservableList<T> childs;
private T parent;
public void addChild(T unit){
childs.add(unit);
unit.setParent(this);
}
public <T> void setParent(T parent){
this.parent = parent;
}
}
I get this message on setParent:
Incompatible types.
Required: T
Found: T
How can i fix this?
Rewrite this:
public <T> void setParent(T parent){
this.parent = parent;
}
With this:
public void setParent(T parent){
this.parent = parent;
}
Also I would suggest to remove the wildcare in the class name declaration, as the code would not compile.
So replace this:
class TreeItem<T extends TreeItem<?>>
With this:
class TreeItem<T extends TreeItem>
You have a final variable in your class. So it should be initialized either in constructor or inline. As long as you use generic variable and generic type is resolved when you instantiate a new object, the right way to do is to initialize it in constructor like this:
public TreeItem(ObservableList<T> childs) {
this.childs = childs;
}
When you are done with the above proposed changes you may notice that the compiler warns you with the message: Unchecked call to 'setParent(T)'. That means that the compiler does not guarantee the code is safe during runtime and possible heap pollution may occure.
I will illustrate it with an example. The following code while running ends up with ClassCastException as we set parent variable with the type which is not T (it is possible due to type erasure).
class ChildTreeItem<T extends TreeItem> extends TreeItem<T> {
public ChildTreeItem(ObservableList childs) {
super(childs);
}
}
public class TreeItem<T extends TreeItem>{
private final ObservableList<T> childs;
private T parent;
public TreeItem(ObservableList<T> childs) {
this.childs = childs;
}
public void addChild(T unit){
childs.add(unit);
unit.setParent(this);
}
public void setParent(T parent){
this.parent = parent;
}
public T getParent() {
return parent;
}
public static void main(String[] args) {
ChildTreeItem<ChildTreeItem> treeItem =
new ChildTreeItem<>(new ObservableSequentialListWrapper<>(new ArrayList<>()));
TreeItem<ChildTreeItem> parentItem =
new TreeItem<>(new ObservableSequentialListWrapper<>(new ArrayList<>()));
parentItem.addChild(treeItem);
List<ChildTreeItem> itemList = new ArrayList<>();
itemList.add(treeItem.getParent()); //<------------------- Heap pollution
ChildTreeItem childTreeItem = itemList.get(0); //<-------- ClassCastException
}
}
The possible solution to this problem is to not parametrize the variable parent but to make it TreeItem type:
public class TreeItem<T extends TreeItem>{
private final ObservableList<T> childs;
private TreeItem parent;
public TreeItem(ObservableList<T> childs) {
this.childs = childs;
}
public void addChild(T unit){
childs.add(unit);
unit.setParent(this);
}
public void setParent(TreeItem parent){
this.parent = parent;
}
public TreeItem getParent() {
return parent;
}
}
Hope this helps.
Since you have define already in your class level of Generic type. It is not clear why you put before your setParent function. But let's assume you want to define a generic type in function level, then when you call it, you need to specify the type
Ex:
TreeItem<String> treeItem = new TreeItem<String>();
treeItem.<String>setParent("something");
I have an abstract class, and I want to force its subclasses to reference an Enum member. Here's a simplified version of what I have:
public abstract class Action {
public static enum ImpactType {
Size(2), Position(2), Scale(1)
final int elements;
private ImpactType (int elements){
this.elements = elements;
}
}
protected abstract ImpactType impactType();
protected abstract apply(float value, int element);
public void apply(float value) {
for (int i=0; i<impactType.elements; i++)
apply(value, i);
}
}
and an example implementation:
public class PositionAction extends Action {
Vector2 target;
public PositionAction(Vector2 target){
this.target= target;
}
protected ImpactType impactType(){ return ImpactType.Position; };
protected abstract apply(float value, int element){
switch (element){
case 0:
target.x = value;
break;
case 1:
target.y = value;
break;
}
}
}
The problem is that this doesn't enforce the impactType method returning the same thing every time. In fact, two different instances of the subclass could potentially return different ImpactTypes, but I need to be sure that each subclass is locked to a single member of the enum because of other operations I'm doing on these objects. Any ideas of how to solve this?
You can enforce the restriction by requiring the subclass to provide an ImpactType on construction.
public abstract class Action {
private final ImpactType m_impactType;
Action( ImpactType impactType ) {
m_impactType = impactType;
}
protected final ImpactType impactType() {
return m_impactType;
}
...
}
Then your subclasses can provide their impact type via super():
public class PositionAction extends Action {
private Vector2 target;
public PositionAction(Vector2 target){
super( ImpactType.Position );
this.target= target;
}
...
}
Final methods can't be overridden. This allows you to lock an implementation so it can't be changed by subclasses.
protected final ImpactType impactType(){ return ImpactType.Position; };
Alternatively, you can do as #javaguest suggested and simply make the ImpactType a private final field with a public getter.
I have a class
private class BSTNode<E extends Comparable<E>> implements Comparable<E> {
BSTNode<E> left, right;
E data;
with constructor and compairTo method
but when I want instantiate the BSTNode class I face problem.
public class BST {
private BSTNode<E> root;
/* Constructor */
public BST() {
root = new BSTNode<E>();
}
how should I use BSTNode in my BST class ? Thanks
Something on these lines (not full fledge or concrete):
public class BST<E extends Comparable<E>>
{
private class BSTNode<E extends Comparable<E>> implements Comparable<E> {
BSTNode<E> left, right;
E data;
#Override
public int compareTo(E o) {
return 0;//implement method here
}
}
private BSTNode<E> root;
public BST() {
root = new BSTNode<E>();//while comparing you would need to case E to comparable and call compareTo method
}
public static void main(String[] args)
{
BST<String> messages = new BST<String>();
}
}
Your class header means that your BTSNode may only be instantiated with classes E which implement the Comparable interface.
As such, you should be able to use it as below:
public class BST {
private BSTNode<Integer> root;
/* Constructor */
public BST() {
root = new BSTNode<Integer>();
}
}
Integer may be replaced with any of the other implementing classes listed here or your even own custom implementation.
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);
}
}
So I have an AbstractSyntaxTreeNode.java class (here is part of it)
public abstract class ASTreeNode implements Iterable<ASTreeNode>{
protected List<ASTreeNode> children;
protected ASTreeNode(){
children = new LinkedList<ASTreeNode>();
}
protected ASTreeNode(ASTreeNode... children){
this();
for(ASTreeNode c: children)
{
this.addChild(c);
}
And then I have another class Operation that extends ASTreeNode
public class Operation extends ASTreeNode
{
char s;
private Operation(Term t)
{
//QUESTION REGARDING THIS PART
super(t, t.getChild(0), t.getChild(1));
}
}
How do I throw in all of object t's (which also extends ASTreeNode) children into the super ctor arguments? Without hardcoding it like that? I tried super(t, t.children) but the constructor does not take a List in the argument, only ASTreeNodes
are taken.
Oh and this is class term
public class Term extends ASTreeNode
{
char symbol;
private Term(Factor f)
{
super(f, f.getChild(0));
}
}
And theres a bunch more classes that send up their children into another node
Add a constructor in ASTreeNode that accept's a List as it's argument.
public abstract class ASTreeNode ... {
public ASTreeNode(List<? extends ASTreeNode> children) {
this.children = children;
}
}
public class Operation extends ASTreeNode {
char s;
private Operation(Term t) {
super(t.getChildren());
this.addChild(t);
}
}