I am writing some java code and I want to write methods in my main class Array. This class implements ImplementableClass. The former extends Iterable. The Array class has an type.
ImplementableClass.java:
public interface ImplementableClass<E> extends Iterable<E>{
public void insertObject(E obj);
public E removeObj(E obj);
}
Main.java:
public class Array<Integer> implements ImplementableClass<E>{
public void insertObject(E obj){
}
public E removeLastObject(E obj){
}
//... main method and others below...
}
I have some questions regarding the code in the two files above.
Reading the java documentation, Iterable is of type E (generic value). From what I understand, interfaces are just "blueprints" of the methods that MUST be used in the class that "implements" them. From a basic point of view, there shall not be any variables in here. With that being said, as you may see I am indeed declaring the methods in my ImplementableClass in Main as well. With that being said, I have a couple of questions:
When declaring my methods from ImplementableClass class in my Array class, this "overrides" the methods from my ImplementableClass class right?
Since "E obj" is the argument in both methods, do they have to be the same whenever I declare my methods in my Array class? What should I pass to the methods? What does "E obj" mean?
I want to create an array that can hold objects of type E. This means that whenever I instantiate a new object-> Array<Integer> theArray = new Array<Integer> I can call the methods I have on my Array class on theArray instance right? (i.e theArray.removeLastObject() ) What should I pass as an argument?
Why would Iterable<E> be of use in this case?
When declaring my methods from ImplementableClass class in my Array class, this "overrides" the methods from my ImplementableClass class right?
Yes (well, not technically since there's no functionality in an interface to override, but you can use #Override to indicate you're overriding it)
Since "E obj" is the argument in both methods, do they have to be the same whenever I declare my methods in my Array class? What should I pass to the methods? What does "E obj" mean?
They need to be the same as the generic type you've specified when you implement the interface. E obj means that you've declared a parameter called obj that is of generic type E. This means that you're required to define the methods to take that particular type as a parameter.
It would make more sense though, to define the generic type of your interface in the declaration, such as:
public class ArrayClass implements ImplementableClass<Integer>
so you can have methods like:
public void insertObject(Integer obj) {}
public Integer removeObj(Integer obj) {}
Or else you can make your Array class generic, and leave the specification of the generic type to the caller:
public class ArrayClass<E> implements ImplementableClass<E>
I want to create an array that can hold objects of type E. This means that whenever I instantiate a new object-> Array theArray = new Array I can call the methods I have on my Array class on theArray instance right? (i.e theArray.removeLastObject() ) What should I pass as an argument?
In order to do that, you would need to make your Array class generic, like shown above. The argument you pass in would be the same type you specify when you create the array (Integer in your example).
Why would Iterable be of use in this case?
Iterable is of use so you can make use of the iterator features of an array, and the enhanced foreach syntax (for (Object o : someObjectArray) {...})
Also, I would suggest not naming your Array class Array... and perhaps look at making use of already existing Iterable classes to construct what you're doing, but this looks like a learning exercise, so have at it.
HTH
What's actually happening is that you're implementing the interface, not overriding it. Since interfaces (in Java <= 7) don't have an implementation, there's nothing for you to really override. You can use the #Override annotation to indicate that you're implementing a method from an interface.
You whiffed on the generics in your second class. If you really want it to be generic (that is, it can be bound to any object), then you want this declaration:
public class Array<E> implements ImplementableClass<E>
That <E> is called a type parameter, and it's applied at the class level, meaning any non-static method or field in the class may make use of it.
E obj is stating that you are willing to accept whatever type of object comes in as an argument. If you declared Array<Integer> intArray = new Array<>();, then E obj would translate internally to Integer obj instead. There's a decent amount of complex operations related to generics; reading up on it would be best.
Be specific as to what kind of data structure you want to use. Arrays and generics do not mix well. If you're creating a generic object array (as in, E[] backingStore), then creating a generic array would be a consideration to take into account.
Honestly, I'd recommend you use a List instead.
Iterable means that the object you have can be iterated with an enhanced-for statement. Why you'd want to do this is subject to your discretion, but that's why you'd want to use that particular interface.
Related
I need to pass Class<TableEditInfo<Generic Type>> to a method to create an array of that generic type, but I am not sure how to get TableEditInfo.class with a generic. I have tried this:
TableEditInfo<Integer> editInfo = new TableEditInfo<Integer>(someData);
c.add(editInfo.getClass(), editInfo)
but it shows me Unchecked cast: 'java.lang.Class<capture<? extends app.mainWindow.edit.TableEditInfo>>' to 'java.lang.Class<app.mainWindow.edit.TableEditInfo<java.lang.Integer>>'. It works but I don't know if this code is correct or is it not a good practise to do that. If its bad, how do I do it properly?
c is other class object that stores the TableEditInfo<T> array
add looks like that:
public void add(Class<TableEditInfo<T>> type, TableEditInfo<T> editInfo){
#SuppressWarnings("unchecked")
TableEditInfo<T>[] arr = (TableEditInfo<T>[]) Array.newInstance(type,1);
arr[0] = editInfo;
stack.push(arr);
}
basically it makes a singleton array, because I just need it for some specific reason.
The expression editInfo.getClass() has type Class<? extends TableEditInfo>. The ? extends is because the object's actual runtime class could be a subclass of TableEditInfo, and the lack of <T> is because there aren't really Class objects representing TableEditInfo<Integer> or TableEditInfo<String>, etc. -- there is only one Class instance at runtime representing the class TableEditInfo.
In any case, the simplest solution is to just remove the type parameter, which is useless. At runtime, the passed argument will always be the same -- it will point to the single Class instance representing the class TableEditInfo, namely, TableEditInfo.class.
You can replace Array.newInstance(type,1) with either new TableEditInfo[1] or new TableEditInfo<?>[1]. Both of those are legal. (The former can be assigned to TableEditInfo<T>[] directly with an unchecked conversion warning. The latter needs a cast to be assigned to TableEditInfo<T>[], which will cause an unchecked cast warning.)
I want to have a list of objects that all inherit from the same interface that contains the function go().
public interface goers{
public void go();
}
Now I have 3 classes that all implement go, for the sake of simplicity let's just call them A, B, and C.
In another class I have a List<Class<? extends goers>> that I want to do.
for (Class<? extends goers> gos : list)
{
gos.go();
}
But it won't compile because the compiler doesn't pick up the go method from the interface being applied to all of the members of the list.
A List<Class<? extends goers>> doesn't have a goers instance that you can call .go() on. You just have classes, not any instances of that classes. There's nothing to call .go() on.
You could try instantiating those classes, or having a List<goers> in the first place, which lets you call it how interfaces are intended to be used.
Because go() is not a method of Class<T>, you cannot call that method on an instance of Class<T>. You have to use only methods of https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html.
If you want an instance of goers [sic - follow the naming conventions] you need to get one somehow. You could use, for example, https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#newInstance--.
Your essential problem is that you're using reflection, an advanced technique that is easy to abuse and hard to get right. Why don't you pass a list of instances of goers [sic - follow the naming conventions] instead of Class objects?
Say, for example, that I have
public class Foo<Game> extends ArrayList<Game>{
}
and I want to iterate over its elements. I'm aware that I can use a for loop with an its iterator. But trying something like:
for(Game g : super)
does not seem to work. This is mysterious(at least to me) because super is a reference to an object of type ArrayList<Game> which should be able to be iterated over. Is there some syntax that I'm missing?
EDIT: I added the Foo type to the class declaration.
This is mysterious(at least to me) because super is a reference to an object of type ArrayList<Game> [...]
super is not an object. If you instantiate a class that inherits from another class, you don't get two objects (this and super), there is only the one instance. (Heck, it'd become unwieldy with deep inheritance hierarchies!) super allows you to access methods from the super class (again, not an object) and use them in your method implementations. Those super methods still execute in the context of the this object, but now that object is of a subclass type. That's perfectly fine though, and it's one of the foundations for polymorphism.
this is an object: it's an instance of Foo and, because Foo inherits from ArrayList<Game>, it is also an ArrayList<Game> and thus implements Iterable<Game>. Therefore, you can just iterate over this.
Thus, you're looking for:
for (Game g : this) { ... }
We have a discussion in office and cannot understand which approach is better
I have a class (SomeClass) with some method which receives Serializable object. The signature is following:
public void someMethod(Serializable serializableObject){
...
}
And I need to call this method from another class, but I should provide it with some List as fact parameter. There are two different approaches
1. Serializable
private SomeClass someClass;
public void doSomething() {
List<String> al = new ArrayList<String>();
al.add("text");
someClass.someMethod((Serializable)al);
}
2. ArrayList
private SomeClass someClass;
public void doSomething() {
ArrayList<String> al = new ArrayList<String>();
al.add("text");
someClass.someMethod(al);
}
Benefit of the first example is that it adheres to the java’s best practices which says: use interface instead of concrete realization for reference type and any programmer while reading that source will understand that we don't need special behavior of the ArrayList. And the only place we need it's serializable behavior we are adding this behavior by casting it to the Serializable interface. And programmer can simply change this current realization of the List to some other serializable realization, for example, LinkedList, without any side affect on this element because we use interface List as it`s reference type.
Benefit of the second example is that we refer to ArrayList as to class which have not only List behavior but also Serializable behavior. So if someone looked at this code and tried to change ArrayList to List he would receive a compile time error which would reduce time for programmer to understand what is going on there
UPDATE: we can't change someMethod signature. It came from a third-party company and we use it not only for Serializable Lists but also for Strings, Integers and some other Serializable objects
You should use an interface when all you need is the methods an interface provides. (this is most cases) However, if you need more than one interface, you can use generics, but the simplest approach is to use the concrete type.
It's better to define ArrayList because this combines two interfaces - List + Serializable. You need both of them in one place.
It doesn't matter that much, but not that using interfaces should be applied more strictly for return types, and less strictly for local variables.
I would change the signature of the someMethod so that it reflects what it requires from the invoker of the method:
public class SomeClass {
public <T extends List<? extends Serializable> & Serializable> void someMethod(T t) {
}
public static void main(String[] args) {
SomeClass test = new SomeClass();
test.someMethod(new ArrayList<String>()); //Works
test.someMethod(new ArrayList<Image>()); //Compile time error, Image is not Serializable
List<String> l = null;
test.someMethod(l); //Compile time error
}
}
The signature of someMethod now says that you must invoke it with something that is a List, and that is Serializable, and contains elements that are Serializable
In this case, I would just use List, and not worry that the compiler cannot guarantee that your object is serializable (it most likely will be anyway, if you've done things right elsewhere).
Note that methods of the following type (which accept a Serializable parameter) provide a false sense of security, because the compiler can never guarantee that the entire object graph which needs to be serialized will actually be serializable.
public void write(Serializable s);
Consider an ArrayList (serializable) which contains non-serializable objects. The signature may as well just be:
public void write(Object o);
And then you don't have to worry about all the extraneous casting.
Also consider that, although you cannot change the signature of the API you are using, you can very easily create a wrapper API which has a different signature.
1 is generally the right thing to do. However in this case, my opinion would to be bend that and declare it as ArrayList<>. This avoids the cast and guarantees that someone can't change the implementation of the List to one that isn't Serializable.
You can't do (1) because you're not free to change the List implementation type arbitrarily, which is the whole idea of doing that. You can only use a List implementation that implements Serializable. So you may as well express that in the code.
Please explain the custom 'T' in the java interface. It is using generics here and of type 'T' i suppose. Then where is the type 'T' defined?
public interface TemplateBuilder<T extends TemplateBuilder>
T is not an actual class. It is determined at compile time depending on the usage of your class TemplateBuilder. Just think of it as a place holder for various possible types, one of which is 'chosen' depending on your circumstances.
For a simpler example, look at the following (adapted from Java's tutorial):
Imagine you want to declare a class Box, which can take a specific type (of the object to hold inside the box), but you wish to reuse this in various circumstances to hold various different types.
So instead of fixing the actual type the Box can take, you declare it as follows:
public class Box<T> {
private T t; // T stands for "Type"
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
When you use it, you then do something like:
Box<Integer> integerBox = new Box<Integer>();
Whats the whole point you might ask? Why not make Box take an Object?
In fact before Java 1.5 this was not possible. This was introduced to have further type-safety in these situations, and was adopted in the Collections framework.
The whole point is that without this mechanism, if instead it used Object, you can't force a specific instance of your Box to hold only Integers. On the other hand, if you made it use specifically Integers, you can't reuse your Box for String, or other objects, and you would need to create another type of Box class.
Before Java 1.5, objects like ArrayList took plain Objects, however there were often cases of type safety broken at runtime, because the program is assuming a list of Integer objects and by mistake somewhere a String is inserted. Generics (through this magic T) force types without restricting what they might be.
In your case T extends TemplateBuilder is going one step further and stating that whatever T is, it must be a class that extends TemplateBuilder. If that wasn't there, it would be any class that extends Object (the universal base class of Java).
T is any Object that extends from TemplateBuilder
T means any Object. for example
List<T> list = new ArrayList<T>();
here T can be Integer, String ...
and <T extends A> means any Object T extends from A
This type is defined when implementing the interface, i.e.
class StringBuilder implements TemplateBuilder<StringBuilder> {}
BTW, see class Enum (the base class of all enums).
My Custom Generics Explanation
Backgorund:
Custom generics are used invariably with data structures e.g. when managing(storing/retrieving) lists of "things"
You do not need to do your own type checking in order for the code to compile as custom generics incorporates the principles of polymorphism.
However, in contrast to the "traditional" OO principles of polymorphism, a class can store a list of things without having any relationship with the "thing(s)" it is storing (The Fundamental Principle of OO where A is a super class of B class is not required)
You do not make separate subclasses for every possible kind of class of "things" you wish to store.
Example 1
As an example consider the following two classes below which are unrelated. This is a very primitive example but nonetheless gives an outline of the principles of custom generics:
/**
*
* Class A is a Custom Generic class that can be 'typed'
* to any kind of class using diamond 'T' syntax.
*
*/
class A<T>
{
// The instance variable of the object type 'T' known at run time
T theI;
// The constructor passing the object type 'T'
A(T anI)
{
this.theI = anI;
}
// Method to return the object 'T'
T getT()
{
return theI;
}
}
Below is the class B which is unrelated to class A i.e. B does not extend A:
/**
*
* Simple class which overrides the toString()
* method from Object's class toString() method
*
*/
class B
{
#Override
public String toString()
{
return "B Object";
}
public static void main(String[] args)
{
A<B> a = new A<>(new B());
System.out.println(a.getT());
}
}
In Main method of class B above:
a.getT() returns the object 'T' which in this example is of type 'B' (This is an example of polymorphism).
a.getT() returns the object 'T', object instance C's method toString() gets IMPLICITLY called, as it is overriding Object's toString() method and prints "B Object".
The interesting aspect to note about Custom Generics and polymorphism is that:
In the context of custom generics, there are no constraints for a relationship among classes in order to execute polymorphism
e.g. Class B is unrelated to A above i.e class B DOES not extend A.
In "traditional" object orientated polymorphism principles, there is invariably a requirement constraint for classes to be related in some way. However, this is not required in custom generics.
Example 2
public interface TemplateBuilder<T extends TemplateBuilder>
The above means that TemplateBuilder interface can be typed to any class that extends TemplateBuilder.
Let's assume SomeClass extends TemplateBuilder then the following is fine:
TemplateBuilder<SomeClass> tbRef = ...
/* Using an Anonymous Inner Class reference to interface TemplateBuilder<SomeClass> */
or
TemplateBuilder<SomeClass> tbRef = .... /* Referencing a concrete class
that implements TemplateBuilder */