I'm very new to Java. This is probably a stupid question--but i can't find the answer anywhere. If you wanted to declare a method that would take in an unknown object and do something with it (copy it, for example), what would be the difference between something like:
<T> T func(Class<T> cls){
//do something
}
Object func(Object o){
//do something
}
Are they comparable? Is there anything you could/would do with one of the above methods and not the other? And where does Class<?> fit in?
The difference in your code is that former func receives a Class<T> (which can be Class<?>) which means the method only receives a Class type . The latter receives any object, regardless if it's a class or another kind of object.
From Class javadoc:
Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions.
Note that Class is metadata for your classes.
If your code were like this:
<T> T func(T o){
//do something
}
Object func(Object o){
//do something
}
The main difference is the return type: the former return type should be as the same type of the argument, while the latter is a generic Object. For example:
Object func(Object o){
//do something
return o.toString(); //compiles and works
}
<T> T func(T o){
//do something
return o.toString(); //does not compile
}
Class is a very specialized type of an object. Class<T> is not a replacement for any kind of object, it is rather a class descriptor. In Java, where everything is an object, also classes are objects, so there is this type - Class - which abstracts over the "class" class of objects.
Here's an example:
If you have this:
Class<Object> obj = Object.class;
func(obj);
, this doesn't mean that inside your func method you will have access to an Object instance; you will have access to a Class<Object> instance, which is he descriptor of the Object class.
So, to answer your question, you should use Object for your declared purpose.
Class and Object are 2 different things in Java. If you wanted to take any type of object, which you don't care the type of, the following is more normally seen.
Object func(Object o){
//do something
}
It is more common to declare functions with Object vs Class, since there are a few more steps for passing a class than an object.
lets hava a look at your functions
<T> T func(Class<T> cls){
//do something
}
this one takes class as parameter, and returns instance of the class,
imagine method as black box which do some magic stuff
you enter String.class and you will get "hello world"
second one
Object func(Object o){
//do something
}
takes object as parameter and returns object, so in theory, you can insert class and returns instance, but you can also put date and received String
The first function accepts a java.lang.Class (that is also an instance of an Object class, because Class extends it. You can find more information about the Class class in the javadoc: http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html ).
Hence the first method can do something with an instance of Class and it does not accept all objects (note the capital letter, it is a name of a class).
The second method accepts all objects (because every object extends java.lang.Object). (Object's javadoc: http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html)
So if you want to create a method that may "take in an unknown object and do something with it" you have to use the second method. You should also know that usually you do not need a method that accepts any object or unknown object and you should not create such methods if you can find another solution (because it causes the code to be harder to read).
A method that accepts Class as an argument is useful when you want to do something with the definition of a class (retrieve a list of fields, methods, constructors etc.). This webpage explains how you can use the Class class: http://docs.oracle.com/javase/tutorial/reflect/index.html
Additionally, if you want to learn more about generics you should read this tutorial: http://docs.oracle.com/javase/tutorial/java/generics/
Related
Let's say I've a java base class:
class base {
public Class<? extends base> type;
// ...
}
type stores the classtype of classes which inherit from base
There's another class which stores base objects in a container, it also has a get method which returns objects stored in that container:
class container {
private Vector<base> v;
//...
public <something here> get(int i){
base b=v.get(i);
return b.type.cast(b);
}
How do I implement such a function(container.get), which casts the object to it's correct type before returning it?
It would be nice to be able to program in a cascading style:
JSONObject o;
//...
o.get("nestedObject").get("array").get(3);
You may be misunderstanding what a "cast" is in Java. Except for casts that involve primitive types (such as casting an int to a float), casts don't change objects at all.
One of your instance variables is
private Vector<Base> v;
(Please use the Java convention and start class names with upper-case letters. I've changed base to Base to set a good example.)
The objects that you put in this vector can be of type Base or any subclass of Base. The type of the object is fixed when the object is constructed. Suppose Base has three subclasses, Child1, Child2, and Child3. Those objects can be construted with new Child1(...), new Child2(...), new Child3(...). As soon as you say new Child1(...), you have an object whose type is Child1, and you can't do anything to change that. But since a Child1 is a Base, you can use your Child1 anywhere you can use a Base, such as putting it into your vector v.
Casting just causes the compiler to look at a variable differently. Suppose you say
Base x = v.get(i);
x (if not null) will be a Base or some object of a subclass. The type of x will be whatever you used to construct the object. Now if you say
Child1 y = (Child1)x;
If x is a Child1, y will be a reference to the same object as x. But the compiler will know that y is a Child1, and you can access new methods that are defined in a Child1. (If x isn't a Child1, you get an exception.) But it's important to note that a cast does not create a new object and it does not change the type of anything. It just tells the compiler to look at a variable or expression in a different way.
Given this, you cannot gain anything by trying to write a method that returns a "variable" type. You may as well just write
public Base get(int i){
return v.get(i);
}
The object that it returns could be a Base, Child1, Child2, etc.; it will be the same type as the object was when you put it into the vector. When you call get, if you are expecting the result to be a Child1, you can say
Child1 child = (Child1)container.get(n);
which will throw an exception if the object isn't a child1. Or you can use instanceof to check yourself:
Base child = container.get(n);
if (child instanceof Child1) {
...
}
If this isn't good enough, you'll need to explain more clearly what you want to accomplish and why this won't work.
MORE: After reading your edit, that says you want to do something like this:
JSONObject o;
//...
o.get("nestedObject").get("array").get(3);
You don't need any casting to accomplish this. What you need is an abstract JSONValue base type that represents any kind of value that can be returned from a JSON parser. The subclasses would be things like "object", "array", and whatever scalar types you need (integer, string, etc.). get would return JSONValue. In actuality, it will return an object of one of the other types, but all the compiler needs to know is that it returns JSONValue.
Now a JSONValue will need two get methods, one that takes a String and one that takes an int or Integer. These will be polymorphic methods. Say v is a JSONValue and you say v.get("array"): the method it actually calls may be different based on the actual type of v. So if v is your "object" type, it will call the method you've defined for the object type; if v is an integer type, it will call the method defined for the integer type, and so on. What you want is for the get method that takes a String to look up the field for the JSON "object" type, and throw an exception for everything else. Similarly, for the get method that takes an integer parameter, the method for the JSON "array" type will look up a list or something, and the method for every other subclass of JSONValue will throw an exception. No "casting" is needed for this. Casting is a compile-time concept. At all points, the compiler will know only that it's working with a JSONValue. But at run time, the object's actual type is used to determine which method to call, so the compiler doesn't need to know anything more.
This is a basic concept that all Java programmers need to know (also Javascript, Python, and pretty much every other language these days, although polymorphism is handled differently in interpreted languages like Javascript and Python). The tutorial https://docs.oracle.com/javase/tutorial/java/IandI/index.html covers this and related concepts. There may be better Java tutorials on "polymorphism" out there also.
type stores the classtype of classes which inherit from base
This is equivalent to this.getClass().
How do I implement such a function(container.get), which casts the object to it's correct type before returning it?
Not possible in theory. People will create more subclasses and put it in the container, after the code is compiled and shipped. That's the purpose of have a base class -- so that the other part of your codebase only has to work with a single interface/concept.
So basically what you want to write is just some generic container code.
interface Container<T extends Base> {
public T get(int i);
}
But the real question was How can the container accommodates a set of known subclasses? Just use different method names. Gson does it.
public class Container {
public Base get(int i) { ... }
public SubType1 getAsSubType1(int i) { ... }
public SubType2 getAsSubType2(int i) { ... }
}
And you can add custom cast methods to Base too.
You can't do that. Generics doesn't really work that way. There's no way to know the exact subtype of your object at compile time.
This b.type.cast(b); casting will need to be done on the result of your method public <something here> get(int i) wherever it's called.
If you have designed the system well you won't need to cast the object back to the exact subclass much, if at all.
Otherwise your best bet is to do a instanceof type check where needed.
I think you are referring to Generics
class container<GenericType> {
private Vector<GenericType> v;
//...
public GenericType get(int i){
GenericType b=v.get(i);
return b;
}
}
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.
I'm trying to make my code more polymorphic. Right now I have a superclass that has four different subclasses. I have a method that accepts the superclass as a type. I want to perform some generic actions before routing it to a different method to handle other actions. Here's what I am envisioning:
public void performSomething(Super object) {
//do some generic action each time to object
object.setSuperProperty();
//now route to appropriate method to perform specific action
doSpecific(object);
}
private void doSpecific(SubA object) { }
private void doSpecific(SubB object) { }
private void doSpecific(SubC object) { }
private void doSpecific(SubD object) { }
This way if I want to add more functionality -- by creating a new subclass or whatever -- then I just need to add another method with the correct subclass type. However, this is not possible since the compiler complains about not having a doSpecific(Super object) method. Instead, in performSomething(Super object) I have to do an ugly:
if(object instanceof SubA)
doSpecific((SubA)object);
else if(object instanceof SubB)
doSpecific((SubB)object);
...
Is there a better way to do this than having to perform all the instanceof checks? Is there a design pattern that I'm not thinking of? I know that I'll lose the compile-time type check safety, but just curious what other solutions could possibly exist.
edit: Forgot to mention this. performSomething and doSpecific are part of an unrelated class I'll call ClassA. I considered creating an abstract method in the Super class so that the subclass could properly implement it. The problem is that performSomething and doSpecific depend on roughly 8 different members of ClassA. So if I wanted to delegate the method to the subclass it would require a ton of parameters like subB.doSpecific(int, int, String, String, Object, int, long, blah, blah); which I'm not sure is better than the original instanceOf check. This would also create a tight coupling between ClassA and the Super/Sub classes I have, when doesn't seem right since I just need to read values from them.
I recommend the Command Pattern.
That means: Every of your subclasses implements a doSpecific() method. Then your initial method looks like this:
public void performSomething(Super object) {
//do some generic action each time to object
object.setSuperProperty();
//now route to appropriate method to perform specific action
object.doSpecific(...);
}
The compiler picks the method of the subclass automatically - no instanceOf check for you.
I just started to learn java and i found out that, to call a method of normal class we need object but for static class we do not need any object to call we can use class reference to do that. But while coding I came across some code which really confused me. The code is.
public class MyInterceptor extends AbstractInterceptor {
#Override
public String intercept(ActionInvocation actionInvocation) throws Exception {
String result = actionInvocation.invoke();
Here my doubt is in the 3rd line we have a reference actionInvocation for a class ActionInvocation and we have not used any new keyword and now check the 4th line we used actionInvocation to access the methos invoke(). How is this possible without using new keyword? I also checked that ActionInvocation is abstract interface.
The new keyword is only used to construct an object. Once it has been created, it can be passed around between methods, other classes, and other places where an object may be stored or transmitted.
You are making a method of MyInterceptor that accepts an ActionInvocation object. This object can either be passed as null, or would have been created elsewhere. You can perform a not-null check (via actionInvocation!=null) to ensure that you're indeed passed an object.
Also, you should remember that you yourself can create objects without using new in your class. There are such ways called factories, where you call a static method such as ByteBuffer.allocateDirect( and that internally uses the new keyword to create an instance of ByteBuffer.
That's perfectly fine code. The ActionInvocation instance is created elsewhere and passed to the intercept(...) method. In fact ActionInvocation actionInvocation is just a reference to an object of a class that extends or implements ActionInvocation, i.e. the actual class of that object could be a subclass/implementation of ActionInvocation.
The concept behind this is called polymorphism: an object of a certain class is also an object of its superclasses and/or might be referenced through implemented interfaces.
An example:
Suppose you have an object like this:
Integer someInt = new Integer(1);
You could pass someInt as a parameter to the following methods:
void doSomething( Integer i) { ... }
void doSomething( Number n) { ... }} //because Integer extends Number
void doSomething( Object o) { ... } //because all objects extend Object
void doSomething( Comparable c) { ...} //because Integer implements Comparable (note that I left out generics here for simplicity)
Note that you could also pass null as an object, as the others already stated, but in your case you should be safe to assume that actionInvocation is never null (this is most likely documented in the API docs).
actionInvocation is initialized(with new) in another place of the program.
You will need a little more understanding of how inheritance and interfaces work to understand this. But the overall logic here is that the method is assuming that object of type ActionInvocation is already instantiated, which might not be the case. Anyways you can look at the calling code for method intercept where an object being passed here must have been instantiated by using new.
By the way ActionInvocation is interface so any "subclass" of this interface can call this method. Have a look at the inheritance terminology to understand what that means.
public String intercept(ActionInvocation actionInvocation)
To call this method any where in your program,
you need to have a created object of type ActionInvocation, then and then only you can call that method.
Once you pass to that,The story inside is usual.
In short,
That object created before calling this method and coming here to do the stuff.
Enum is in the java.lang.Enum, and Object is in the java.lang.Object. So, why is Enum not an Object? (I am getting a java.lang.ClassCastException)
I want to make a class that can accept both Object and Enum, like this...
public class MyType<T extends Enum<T>, Object> {
But this gives a compilation error. How can i make my MyType so that it can accept all (or both) type of classes? (Enum or Object)?
Since every Java object is instanceof Object, there is nothing better to do than declare MyType<?> with no bounds. That will capture any type, including an enum type.
An Enum is an Object. See http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Enum.html
So
MyType<Object> {
should work.
You can see on documentation:
Excepting Object, which has no superclass, every class has one and
only one direct superclass (single inheritance). In the absence of any
other explicit superclass, every class is implicitly a subclass of
Object.
You can conclude:
even not explicit your class will extends from Object;
if Object was a figured manner to represent other class, you will not be able since java doesn't support multiple-inheritance.
Simply by looking at the API for class object, you can read:
Class Object is the root of the class hierarchy. Every class has Object as a superclass.
All objects, including arrays, implement the methods of this class.
This means that Enum is an object (you can verify this by looking at the JavaDocs for Enum aswell). Hence, if you simply tell MyType to contain Object(MyType<Object>), it will accept Object and Enum as you originally posted.
Although notice that this might cause unwanted behavior and is considered unsafe, since ALL classes are objects.
I don't think you've stated your question correctly. I think you want your class to accept Enum or Object. When you put it like that you can see that is the only possible choice.
If you want it to accept Enum and Object, that is equivalent to saying 'accept Enum'. In which case > is the answer.