I'm trying to get familiar with generics in java. I'm still unsure how create a simple class to take two types (String, Integer). Below is a trivial attempt at working with generics in my contexts.
public class Container <T>
{
public T aString()
{
//Do i know I have a string?
}
public T anInt()
{
//How do I know I have an integer?
}
public Container<T>()
{
//What would the constructor look like?
}
}
I'm referencing this page oracle generics but I'm still not sure what I'm doing here. Do you first figure out what type your "T" in the class?
Is generic programming genuinely used for interfaces and abstract classes?
Well that Container class can actually hold a String, Integer or any type, you just have to use it correctly. Something like this:
public class Container<T> {
private T element;
public T getElement() {
return element;
}
public void setElement(T element) {
this.element = element;
}
public Container(T someElement) {
this.element = someElement;
}
}
And you can use it like this:
Container<Integer> myIntContainer = new Container<Integer>();
myIntContainer.setElement(234);
or...
Container<String> myStringContainer = new Container<String>();
myStringContainer.setElement("TEST");
If the class does significantly different things for String and Integer, maybe it should be two classes, each specialized for one of those types.
I see generics as being useful for situations in which references of different types can be handled the same way. ArrayList<String> and ArrayList<Integer> don't need any code that is specific to String or Integer.
Class type = Integer.class
Integer i = verifyType("100",type);
for integer, similar with string...
reference Java Generics with Class <T>
If you want to use String and Integer you'll probably have to use Object as the type. This removes most of the benefit of Generics frankly and you should probably check that you actually have a sound model and reason for inter-weaving strings and integers.
But yes, it's useful for interfaces, custom classes and abstracts. It means you can guarantee the object is of the right type and removes the need to implement them each time for each type of thing.
Related
for performance reasons I need to use arrays to store data. I implemented this in a generic fashion like this (see this answer):
import java.lang.reflect.Array;
public class SimpleArray<T> {
private T[] data;
#SuppressWarnings("unchecked")
public SimpleArray(Class<T> cls, int size) {
this.data = (T[]) Array.newInstance(cls, size);
}
public T get(int i) {
return data[i];
}
}
The problem is that I need the involved Class<?>es. However, I might have a more complex class hierarchy containing generics:
public class Outer<T> {
public class Inner {
}
}
I would like to initialize the array as I would with an ordinary class:
SimpleArray<Integer> intArray = new SimpleArray<>(Integer.class, 10);
intArray.get(0);
SimpleArray<Outer<Integer>> outerArray;
// how to initialize this?
SimpleArray<Outer<String>.Inner> innerArray;
// how to initialize this?
I read the post on how to (not) get the Class of something generic (here) but the bottom-line seems to be that everything is type-safety related syntactic sugar.
My question is the following: How can I create instances of the SimpleArray classes above while avoiding as much ugliness as possible?
There are two issues here.
Do you really need to pass in a Class? In this case, no. Your class does not actually need to know the element type at runtime to do its job. For example, you can just do:
public class SimpleArray<T> {
private Object[] data;
public SimpleArray(int size) {
this.data = new Object[size];
}
#SuppressWarnings("unchecked")
public T get(int i) {
return (T)data[i];
}
}
If you really needed a Class<T>, how would you get one? Well, first you need to ask yourself, what are you going to use this for? There will never be a "true" Class<T> for a non-reifiable type T because with a Class<T> you can do things like .isInstance() to check whether something is an instance of T at runtime; but of course it's not possible to check instance-of with non-reifiable types at runtime.
In this case, you're only going to pass it to Array.newInstance(), and Array.newInstance() uses the raw type anyway (it does not care about the compile-time type of the Class parameter -- the parameter type is Class<?> -- it only uses the runtime value of the Class object), it is sufficient to simply coerce a Class object representing the raw type to the appropriately-parameterized Class type:
(Class<Outer<Integer>>)(Class<?>)Outer.class
You seem to be trying to make a class that wraps an array and provides a method to get elements. The class Arrays.ArrayList does exactly that already, so there is no need to reinvent the wheel. It works as follows:
List<String> list = Arrays.asList(new String[30]);
list.set(3, "foo");
System.out.println(list.get(3));
You can't use Arrays.asList to produce a List<T> if the type T is generic without suppressing a warning because it is not possible to create a generic array. You can write a helper method to do this for you though.
#SuppressWarnings("unchecked")
public static <T> List<T> newArray(int size) {
return (List<T>) Arrays.asList(new Object[size]);
}
You can use the returned List to get and set elements without having to cast, even if the type T is generic. For example:
List<List<String>> list = newArray(30);
list.set(4, Arrays.asList("A", "B", "C"));
System.out.println(list.get(4));
I didn't even know this was doable, but I saw while perusing some code online a method with a signature like this:
public List<Void> read( ... )
... What? Is there ever a reason to do this? What could this List even hold? As far as I was aware, it's not possible to instantiate a Void object.
It is possible that this method signature was created as a by-product of some generic class.
For example, SwingWorker has two type parameters, one for final result and one for intermediate results. If you just don't want to use any intermediate results, you pass Void as the type parameter, resulting in some methods returning Void - i.e. nothing.
If there were a method List<V> returnAllIntermediateResults() in SwingWorker with Void as the type parameter V, it would have created a method just like you posted in your question.
The code would be perfectly valid. You can instantiate any implementation of the List interface (e.g. ArrayList) with type parameter Void. But the only value a Void type can have is null. So the list could not hold anything else but nulls, if the implementation allows null elements.
One case in which it may be useful is if you wanted to return a collection of return values from a function. Say
static List<T> forEach(Func<A,T> func, List<A> items) {
List<T> ret = new List<T>();
for(int i = 0; i< items.length; i++) {
ret.add(func.call(items[i]);
}
return ret;
}
public static void main() {
...
List<Void> boringResult =
forEach(
new Func<Void, Integer> {#override Void call(Integer i) {...}});
}
Not that useful but you could see a case where it was required.
List<Void> is weird. It can only have null elements, since you can't create an object of type Void. I don't think there is a practical use for such a thing.
Void is part of java.lang. It's not a special keyword or anything. It's a "pseudo-type" (according to the docs) used to as a place-holder to represent the Class object corresponding to void, as in Class<Void>. From the docs for Class:
The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
The Void class exists mainly for the sake of the last part of this, so you can write:
Class<Void> voidType = void.class; // == Void.TYPE
just like you can write:
Class<Integer> intType = int.class; // == Integer.TYPE
I agree, it's odd.
I can see a use for it if you want to extend a generic class and return void from a method. I've bumped into a case were I want to use int and had to use Integer because java generics don't like primitive types.
public interface ObjectUserPool<E, T> {
public E useObject(T o);
}
public class NonReturningObjectUserPool extends ObjectUserPool<Void, Integer> {
public Void useObject(Integer i);
}
I think this is what the java API is saying, though to be honest I can't really find a use for NonReturningObjectUserPool.
Can a programming language be "complete" without the existence of explicit casting? In essence, is there anything we can't do using a language that lacks explicit type casting?
For example, the post below demonstrates that Java requires explicit type casting to write customized generic-type classes.
Are there any other example use cases where we absolutely need explicit casting?
Here are some
To reverse automatic primative widening:
byte blammy = (byte)(schmarr & 0xF7);
Legacy code:
public void oldSchoolMethod(List oldSchoolListOfStrings)
{
String firstValue = (String)oldSchoolListOfStrings.get(0);
}
HTTP Code:
public String getSchmarr(HttpServletRequest request)
{
HttpSession session = request.getSession();
return (String)session.getAttribute("Schmarr");
}
Edit: "type increases" corrected to "primative widening".
Sure, take the equals method for example - it has to get Object a parameter. (and read this great chapter of Effective Java regarding equals and friends)
In Java, there is no way to declare an array of a generic type T. For example, it is invalid to declare an array using new T[10]:
public class List<T> {
T[] backing_array = new T[10]; // this line is invalid,
public T Item(int index) {
return backing_array[index]; // and therefore this line is invalid as well.
}
//etc...
The best alternative solution we have is this:
public class List<T> {
Object[] backing_array = new Object[10];
public T Item(int index) {
return (T) backing_array[index]; // notice that a cast is needed here if we want the return type of this function to be T
}
//etc...
If explicit type casting did not exist in Java, it would be impossible to build generic array lists, since declare an array of a generic type T is not allowed.
I use casting frequently when dealing with libraries that aren't built with generics in mind, or when I need to down-cast some object to access functionality I know is implemented by a subclass, but not by the class that I'm otherwise using. It's probably wise to check with an if (foo instanceof Bar)
clause before making that cast, though.
When we deserialize an object (for example from a string) we are required to cast the object in to the class so that we can use its methods.
I haven't used generics before and I am wondering when I should use them and what the advantages are. I think it might be appropriate for a collection that I made since java always uses generics for collections as well but if I call the methods I created the type is already set in the function so it would give an error anyway. When should I use a generic class? Could you give an example because I am not sure how to use it. At the moment my code is as follows:
public class NodeList {
private static final int MAX_AMOUNT_OF_NODES = 12;
private HashMap<String, Node> nodeList;
public NodeList(){
nodeList = new HashMap<String, Node>(MAX_AMOUNT_OF_NODES);
}
public Node get(String id){
return nodeList.get(id);
}
public boolean add(Node node){
if(nodeList.size() <= MAX_AMOUNT_OF_NODES){
nodeList.put(node.id, node);
return true;
}
return false;
}
}
You can look at the existing API for guidance. For example, all the Collections are generic. That is because all collections contain elements of a type.
From that, it makes sense that generic classes should be used when you would have to create the exact same code again and again for different types. If you have to do that, generics might offer you some benefit.
As far as an example, the docs are a good place to start.
From that link, the first code sample is
public class Box<T> {
// T stands for "Type"
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
}
Conceptually, there is a Box class that is going to contain something. What it contains does not matter, because the type is specific by the programmer. A Box instance can contain basically anything. When the programmer needs to create a box, he/she specifies the type.
Box<SomeClass> myBox = new Box<SomeClass>();
Think about it this way -- if you wanted to create a general Box that could hold anything without generics, you would have to
1) have the field f be an Object, or
2) create a Box class for every type a box could contain.
With generics, you only need one class, and you can specify the exact type. Maybe if you are doing something and your approach involved either 1 or 2 above, it's better to use generics.
If Node is a class that can hold a piece of data with certain type (like String, for example) then you should generify Node and subsequently NodeList to prevent type errors.
If you don't, then you leave it up to the user of your NodeList to ensure that she never adds an Integer when the list is only supposed to hold Strings. Generics is primarily about catching type problems at compile time rather than runtime.
It's pretty simple to do so, change something like this:
public class Node {
Object data;
//...
}
to something like this:
public class Node<T> {
T data;
//...
}
public class NodeList<T> {
public Node<T> get(String id) {
//...
}
public boolean add(Node<T> node) {
//...
}
}
Your NodeList looks like it could potentially have a second type parameter for the key type, which right now you're constraining to String.
You can generically type the methods arguments as well as the class itself. Here's an example from Java's java.util.List interface:
public interface List<E> {
//...
boolean add(E e);
//...
}
Generics are a way for Java to force a collection data structure (HashMap in your case) to accept only a specific types of objects. This means that at compile time, if you tried something like:
nodeList.add(1, new Node());
it would fail and not compile since 1 is not a String object. It is generally a way to write tidier code.
Check this link as well:http://en.wikipedia.org/wiki/Generics_in_Java
Say that I need to create 3 linked lists one for int, one for Strings and one for a different type of custom object. If I was using generics it would be easy to do this just by creating one linked list but is there a way to avoid writing the same repetetive code 3 times if I was not using generics?
If you use Integer instead of int, then yes. In this case, all three objects are subclasses of Object so your Linked List class could just deal with Objects.
The code would look, roughly, like:
class MyLinkedList{
public void add(Object){...}
public Object remove(Object){...}
...
}
Before the introduction of generics in Java 1.5 the Collections all used the type Object, so you would have a linked list of Objects. You then had to make sure yourself that you were adding, retrieving and casting the right types.
I don't see any reason why you shouldn't or wouldn't use generics since using Java 1.4 is hardly necessary or recommended anymore.
You couldn't use the same code for ints vs Strings, but assuming you meant Integers, then you would have to create a LinkedList that stored java.lang.Objects, which by the way, is what generic based LinkedLists do.
You can abstract out the type that the linked list handles into your own type, say StringOrIntOrCustom, that has one of each type, and a flag that specifies which one is the valid one to use. However, you'd need to do a lot of checking to make sure you're not doing an operation that a type does not support whenever you use this data type.
You could do it with out generics, but you would have no compile time type safety checking and you will have to add all the type casting manually.
But then again you will essentially doing what the compiler does when you use generics. Now it's just error prone and manual.
Yes, you can do this, and it's not that hard.
abstract class ListNode {
public ListNode next_;
};
interface ListNodeFactory {
public ListNode createListNode();
}
You then create a List class the manipulates ListNode objects. It will have a function it calls to create a new ListNode when it needs one. The add method would take a ListNodeFactory argument. I would suggest most of the methods be protected because no client that's not a derived class is likely to use it.
The you create a derived class from List for each type. You will have to wrap each method with one that takes the type you want. You will also have to create a ListNodeFactory implementation that creates new list nodes with the appropriate type in them. It will also have to cast the ListNode objects it gets out from traversals or removals to the appropriate types in order to get at the data. Here is an example:
class IntListNode extends ListNode {
public int data_;
public IntListNode(int x) {
data_ = x;
}
}
class IntListNodeFactory implements ListNodeFactory {
IntListNodeFactory() {
nextdataset_ = false;
}
IntListNodeFactory(int x) {
nextdataset_ = true;
data_ = x;
}
void setNextData(int x) {
nextdataset_ = true;
nextdata_ = x;
}
public ListNode createListNode() {
if (!nextdataset_) {
throw Exception("Tried to create a node with no data!");
} else {
ListNode result = new IntListNode(data_);
nextdataset_ = false;
return result;
}
}
}