I have upcasted Model2 instance in the following code to Object class and then downcasted back to the class - Model2 in the test method of Model1 class. But thenUov its attribute value after downcasting is showing null. Is this expected for the instance to loose its state after Upcasting-then-Downcasting? Could you please share some details for the same. Also, is there a way to retain the state of the instance after upcasting?
public class Demo{
public static void main(String[] args) {
Model1 m1 = new Model1();
m1.setAttr1(10);
Model2 m2 = new Model2();
m2.setAttr2(10);
m1.test(m2);
}
}
class Model1 {
private Integer attr1;
public Integer getAttr1() {
return attr1;
}
public void setAttr1(Integer attr1) {
this.attr1 = attr1;
}
public void test(Object o) {
Model2 m = (Model2) o;
System.out.println(m.getAttr2());
}
}
class Model2 {
private Integer attr2;
public Integer getAttr2() {
return attr2;
}
public void setAttr2(Integer attr1) {
this.attr2 = attr2;
}
}
No, you don't lose data when casting - an Object is the Object it is.
You are getting null due to a typo in Model2
public void setAttr2(Integer attr1) {
this.attr2 = attr2;
}
You are setting attr2 to itself, the function definition should be (Interger attr2)
Changing that will output 10
Casting doesn't loose any information in Java, it simply changes the level of abstraction (i.e you can't access method getAttr2() on 'o' whilst it is still cast as an object)
The real problem is a typo in model2. You are setting the variable 'attr2' to itself, which is set to null to start with
You want it to be this.attr2 = attr1
I realise that this is probably just a test class, but I would like to also point out that it's good practise to check your argument before casting it - you could have been passed a null or an object of the wrong type.
public void test(Object o) {
if (o == null) {
System.out.println("Don't give me a null");
} else if (o instanceof Model2) {
Model2 m = (Model2) o;
System.out.println(m.getAttr2());
} else {
System.out.println("Wrong type. Was given " + o.getClass());
}
}
In a real class you'd actually do something useful in those sections such as throw an exception
Related
In Java, how can you pass a type as a parameter (or declare as a variable)?
I don't want to pass an instance of the type but the type itself (eg. int, String, etc).
In C#, I can do this:
private void foo(Type t)
{
if (t == typeof(String)) { ... }
else if (t == typeof(int)) { ... }
}
private void bar()
{
foo(typeof(String));
}
Is there a way in Java without passing an instance of type t?
Or do I have to use my own int constants or enum?
Or is there a better way?
Edit: Here is the requirement for foo:
Based on type t, it generates a different short, xml string.
The code in the if/else will be very small (one or two lines) and will use some private class variables.
You could pass a Class<T> in.
private void foo(Class<?> cls) {
if (cls == String.class) { ... }
else if (cls == int.class) { ... }
}
private void bar() {
foo(String.class);
}
Update: the OOP way depends on the functional requirement. Best bet would be an interface defining foo() and two concrete implementations implementing foo() and then just call foo() on the implementation you've at hand. Another way may be a Map<Class<?>, Action> which you could call by actions.get(cls). This is easily to be combined with an interface and concrete implementations: actions.get(cls).foo().
I had a similar question, so I worked up a complete runnable answer below. What I needed to do is pass a class (C) to an object (O) of an unrelated class and have that object (O) emit new objects of class (C) back to me when I asked for them.
The example below shows how this is done. There is a MagicGun class that you load with any subtype of the Projectile class (Pebble, Bullet or NuclearMissle). The interesting is you load it with subtypes of Projectile, but not actual objects of that type. The MagicGun creates the actual object when it's time to shoot.
The Output
You've annoyed the target!
You've holed the target!
You've obliterated the target!
click
click
The Code
import java.util.ArrayList;
import java.util.List;
public class PassAClass {
public static void main(String[] args) {
MagicGun gun = new MagicGun();
gun.loadWith(Pebble.class);
gun.loadWith(Bullet.class);
gun.loadWith(NuclearMissle.class);
//gun.loadWith(Object.class); // Won't compile -- Object is not a Projectile
for(int i=0; i<5; i++){
try {
String effect = gun.shoot().effectOnTarget();
System.out.printf("You've %s the target!\n", effect);
} catch (GunIsEmptyException e) {
System.err.printf("click\n");
}
}
}
}
class MagicGun {
/**
* projectiles holds a list of classes that extend Projectile. Because of erasure, it
* can't hold be a List<? extends Projectile> so we need the SuppressWarning. However
* the only way to add to it is the "loadWith" method which makes it typesafe.
*/
private #SuppressWarnings("rawtypes") List<Class> projectiles = new ArrayList<Class>();
/**
* Load the MagicGun with a new Projectile class.
* #param projectileClass The class of the Projectile to create when it's time to shoot.
*/
public void loadWith(Class<? extends Projectile> projectileClass){
projectiles.add(projectileClass);
}
/**
* Shoot the MagicGun with the next Projectile. Projectiles are shot First In First Out.
* #return A newly created Projectile object.
* #throws GunIsEmptyException
*/
public Projectile shoot() throws GunIsEmptyException{
if (projectiles.isEmpty())
throw new GunIsEmptyException();
Projectile projectile = null;
// We know it must be a Projectile, so the SuppressWarnings is OK
#SuppressWarnings("unchecked") Class<? extends Projectile> projectileClass = projectiles.get(0);
projectiles.remove(0);
try{
// http://www.java2s.com/Code/Java/Language-Basics/ObjectReflectioncreatenewinstance.htm
projectile = projectileClass.newInstance();
} catch (InstantiationException e) {
System.err.println(e);
} catch (IllegalAccessException e) {
System.err.println(e);
}
return projectile;
}
}
abstract class Projectile {
public abstract String effectOnTarget();
}
class Pebble extends Projectile {
#Override public String effectOnTarget() {
return "annoyed";
}
}
class Bullet extends Projectile {
#Override public String effectOnTarget() {
return "holed";
}
}
class NuclearMissle extends Projectile {
#Override public String effectOnTarget() {
return "obliterated";
}
}
class GunIsEmptyException extends Exception {
private static final long serialVersionUID = 4574971294051632635L;
}
Oh, but that's ugly, non-object-oriented code. The moment you see "if/else" and "typeof", you should be thinking polymorphism. This is the wrong way to go. I think generics are your friend here.
How many types do you plan to deal with?
UPDATE:
If you're just talking about String and int, here's one way you might do it. Start with the interface XmlGenerator (enough with "foo"):
package generics;
public interface XmlGenerator<T>
{
String getXml(T value);
}
And the concrete implementation XmlGeneratorImpl:
package generics;
public class XmlGeneratorImpl<T> implements XmlGenerator<T>
{
private Class<T> valueType;
private static final int DEFAULT_CAPACITY = 1024;
public static void main(String [] args)
{
Integer x = 42;
String y = "foobar";
XmlGenerator<Integer> intXmlGenerator = new XmlGeneratorImpl<Integer>(Integer.class);
XmlGenerator<String> stringXmlGenerator = new XmlGeneratorImpl<String>(String.class);
System.out.println("integer: " + intXmlGenerator.getXml(x));
System.out.println("string : " + stringXmlGenerator.getXml(y));
}
public XmlGeneratorImpl(Class<T> clazz)
{
this.valueType = clazz;
}
public String getXml(T value)
{
StringBuilder builder = new StringBuilder(DEFAULT_CAPACITY);
appendTag(builder);
builder.append(value);
appendTag(builder, false);
return builder.toString();
}
private void appendTag(StringBuilder builder) { this.appendTag(builder, false); }
private void appendTag(StringBuilder builder, boolean isClosing)
{
String valueTypeName = valueType.getName();
builder.append("<").append(valueTypeName);
if (isClosing)
{
builder.append("/");
}
builder.append(">");
}
}
If I run this, I get the following result:
integer: <java.lang.Integer>42<java.lang.Integer>
string : <java.lang.String>foobar<java.lang.String>
I don't know if this is what you had in mind.
You should pass a Class...
private void foo(Class<?> t){
if(t == String.class){ ... }
else if(t == int.class){ ... }
}
private void bar()
{
foo(String.class);
}
If you want to pass the type, than the equivalent in Java would be
java.lang.Class
If you want to use a weakly typed method, then you would simply use
java.lang.Object
and the corresponding operator
instanceof
e.g.
private void foo(Object o) {
if(o instanceof String) {
}
}//foo
However, in Java there are primitive types, which are not classes (i.e. int from your example), so you need to be careful.
The real question is what you actually want to achieve here, otherwise it is difficult to answer:
Or is there a better way?
You can pass an instance of java.lang.Class that represents the type, i.e.
private void foo(Class cls)
I have a list which is a private member in my class.
I have used getter and setter to get and set the values.
SOnar throws an error - Mutable members should not be stored or returned directly.
For example: ABC and DEF are two classes.
class ABC{
private List<DEF> defList;
public List<DEF> getDefList() { return defList; }
public void setDefList(List<DEF> defList) { this.defList = defList; }
After lot of googling and searching, I have understood that the getter can be changed as follows:
public List<DEF> getDefList() { return new ArrayList<>(defList); }
When i try to use setter similarly,
public void setDefList(List<DEF> defList) { this.defList.addAll(defList); }
then the variable starts showing
'private field 'defList' is never assigned.
May I know the correct way to do when it is a list, (a list of another class)
Note: Both the answers from Prasad Karunagoda and Leo Aso works. I cant mark both as accepted answer. So having a note here
The warning is because you did not give the field an initial value. This is how you should implement the code to ensure immutability using java.util.Collections.
class ABC {
private List<DEF> defList = Collections.emptyList();
public List<DEF> getDefList() {
return defList;
}
public void setDefList(List<DEF> defList) {
// defensively copy, then make immutable
defList = new ArrayList<>(defList);
this.defList = Collections.unmodifiableList(defList);
}
I believe it is better not to add additional restrictions (immutability) to the List returned from the getter. If you do that, clients using your List will not be able sort it for example.
So, my recommended approach is this:
public class ABC {
private List<DEF> defList = new ArrayList<>();
public List<DEF> getDefList() {
return new ArrayList<>(defList);
}
public void setDefList(List<DEF> defList) {
if (defList == null)
throw new IllegalArgumentException("Parameter defList is null");
this.defList.clear();
this.defList.addAll(defList);
}
}
From design perspective, an even better API for ABC class would be:
public List<DEF> getDefList()
public void clearDefList()
public void addAllDefs(List<DEF> defs) // Or method name appendDefs
Given the following abstract class:
public abstract class BaseVersionResponse<T extends BaseVO> {
public abstract void populate(T versionVO);
}
and the following child class:
public class VersionResponseV1 extends BaseVersionResponse<VersionVOV1>
{
protected String testFieldOne;
protected String testFieldTwo;
public String getTestFieldOne() {
return testFieldOne;
}
public void setTestFieldOne(String value) {
this.testFieldOne = value;
}
public String getTestFieldTwo() {
return testFieldTwo;
}
public void setTestFieldTwo(String value) {
this.testFieldTwo = value;
}
#Override
public void populate(VersionVOV1 versionVO) {
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
I desire to do something like this from a calling method:
public void getVersionInfo(String version) {
BaseVO versionVO = null;
BaseVersionResponse<? extends BaseVO> baseVersionResponse = null;
baseVersionResponse = createVersionResponse(version);
versionVO = createVersionVO(version);
baseVersionResponse.populate(versionVO);
}
where createVersionResponse(...) and createVersionVO(...) look like this:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version) {
BaseVersionResponse<? extends BaseVO> specificVersionResponse = null;
if (version.equalsIgnoreCase("V1")) {
specificVersionResponse = new VersionResponseV1();
} else if (version.equalsIgnoreCase("V2"))
specificVersionResponse = new VersionResponseV2();
return specificVersionResponse;
}
public BaseVO createVersionVO(String version) {
BaseVO versionVO = null;
if (version.equalsIgnoreCase("V1")) {
versionVO = new VersionVOV1();
} else if (version.equalsIgnoreCase("V2"))
versionVO = new VersionVOV2();
return versionVO;
}
and VersionVOV1 looks like this:
public class VersionVOV1 extends BaseVO {
private String fieldOne = null;
private String fieldTwo = null;
private String fieldThree = null;
public String getFieldOne() {
return fieldOne;
}
public void setFieldOne(String fieldOne) {
this.fieldOne = fieldOne;
}
public String getFieldTwo() {
return fieldTwo;
}
public void setFieldTwo(String fieldTwo) {
this.fieldTwo = fieldTwo;
}
public String getFieldThree() {
return fieldThree;
}
public void setFieldThree(String fieldThree) {
this.fieldThree = fieldThree;
}
}
My problem arises when I try to compile this line of code:
baseVersionResponse.populate(versionVO);
in getVersionInfo(...). I'm getting a message that looks like this:
The method populate(capture#3-of ?) in the type BaseVersionResponse is not applicable for the arguments (BaseVO)
on the populate method above.
My thought was (which is apparently incorrect) that since the baseVersionResponse is, at this point in the code, actually a specific child instance, that the class would know exactly which populate method to call from that specific child class.
What am I doing wrong here? Is there a better way to do this if this isn't the correct approach?
Thank you for your time!
Ok, I took a better look at this today. The problem is that the wildcard, while the right way to go, precludes you from doing:
BaseVO versionVO = createVersionVO(version);
Because the populate call wants an extension of BaseVO, not an actual BaseVO, which doesn't qualify. That means you can't pass that versionVO variable directly.
So, to keep the type checking in place, which I think is good because you'll always want an implementation, leave pretty much everything as-is above, and change your BaseVersionResponse class to something like:
public abstract class BaseVersionResponse<T extends BaseVO> {
public T getVersion(BaseVO versionVO) {
try {
return (T) versionVO;
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}
}
public abstract void populate(BaseVO versionVO);
}
So, populate method now takes a BaseVO, and there's a new getVersion method to do some explicit casting for us. This should be ok since we know that the factory will always supply the right thing, but if another caller doesn't, an IllegalArgumentException is thrown.
Now, in your response class implementation, change the populate method accordingly:
public void populate(BaseVO version) {
VersionVOV1 versionVO = getVersion(version);
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
So, we've changed the populate method to take BaseVO, and the getVersion method does the casting for us. All the other type checks still apply, and we're good to go.
The casting makes it feel not as clean, but for the factory approach you're using, it's really the only way (I can think of) to keep the guarantees made by the type declarations and the code pattern in tact.
Hope that helps!
If you just take out the capture of type (the "<?>"), and leave it unchecked, it should work just fine. Even using type Object would have compiled.
But, given your specific example, what you probably want is the method:
public BaseVersionResponse<?> createVersionResponse(String version)
Changed to:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version)
Then, instead of using
BaseVersionResponse<?>
use
BaseVersionResponse<? extends BaseVO>
Since you know that the return type will be one of those things that implements the interface/class.
(I was astonished not to be able to find this question already on stackoverflow, which I can only put down to poor googling on my part, by all means point out the duplicate...)
Here is a toy class that returns the reverse of what you put into it. Currently it works on integers, but would require only very minor changes to work for String.
public class Mirror {
int value;
public int get() {
return reverse(value);
}
private int reverse(int value2) {
String valueString = value + "";
String newString = reverse(valueString);
return Integer.parseInt(newString);
}
private String reverse(String valueString) {
String newString = "";
for (char c : valueString.toCharArray()) {
newString = c + newString;
}
return newString;
}
public void set(int value) {
this.value = value;
}
}
What I'd like to do is make the class generic, but only for, say, two or three possible types. So what I want to write is:
public class Mirror<X, where X is one of Integer, String, or MagicValue {
X value
public X get(){
[...]
What's the correct syntax? My Google-fu is failing me... :(
EDIT: it appears there isn't a correct syntax and it can't appear to be done, so my main question is: why? this seems like the sort of thing that people might want to do before they made the class truly generic...
EDIT EDIT: Managed to work out the why with some labmates today, so added the relevant why answer below.
Unfortunately java does not provide such functionality directly. However I can suggest you the following work around:
Create parametrized class Mirror with private constructor and 3 static factory methods that create instance of Mirror with specific parameter:
public class Mirror<T> {
private T value
private Mirror(T value) {
this.value = value;
}
public static Mirror<Integer> integerMirror(Integer value) {
return new Mirror(value);
}
public static Mirror<String> stringMirror(String value) {
return new Mirror(value);
}
public static Mirror<MagicValue> magicMirror(MagicValue value) {
return new Mirror(value);
}
}
EDIT
Obviously you can (and probably should) separate the class Mirror from its creating, e.g. put the factory methods to separate class MirrorFactory. In this case the constructor should become package protected.
If you want to support large yet limited number of classes you can implement only one generic factory method
public static <T> Mirror<T> createMirror(T value) {
checkTypeSupported(value);
return new Mirror(value);
}
Method checkTypeSupported(value); may use some kind of metadatat (e.g. properties, JSON etc file) to get supported types. In this case however you will not enjoy the compile time validation.
Other solution is to require that all supported types extend certain base class or implement interface:
public class Mirror<T extends MyInterface> {}
But this solution seems does not match your requirements since you need Integer, String and MagicValue.
Various ways to do what you need...Here is another option. No getter or setter.
One instance of Mirror for each type to be handled. One reverse() method.
Tweak as necessary. Add error checking/handling.
public class Mirror<T> {
public T reverse(final T value) {
T result = null;
while (true) {
if (value instanceof String) {
System.out.println("Do for String");
result = value;
break;
}
if (value instanceof Integer) {
System.out.println("Do for Integer");
result = value;
break;
}
if (value instanceof JFrame) {
System.out.println("Do for JFrame");
result = value;
break;
}
throw new RuntimeException("ProgramCheck: Missing handler for type " + value.getClass().getSimpleName());
}
return result;
}
Tester:
final Mirror<String> testerString = new Mirror<>();
testerString.reverse("string");
final Mirror<Integer> testerInteger = new Mirror<>();
testerInteger.reverse(41);
testerInteger.reverse(42);
testerInteger.reverse(43);
final Mirror<JFrame> testerJFrame = new Mirror<>();
testerJFrame.reverse(new JFrame());
Results:
Do for String
Do for Integer
Do for Integer
Do for Integer
Do for JFrame
An alternative would be to just accept the fact that you have no control over the type hierarchy of String/Integer and create an interface to give a common type for the classes you do have control over
public int reverse(int value) {
return Integer.valueOf(new StringBuilder(value + "").reverse()
.toString());
}
public String reverse(String value) {
return new StringBuilder(value + "").reverse().toString();
}
public <T extends Reversible> T reverse(T value) {
value.reverse();
return value;
}
public interface Reversible {
public void reverse();
}
And if you only want one instance of the Mirror class...use a generic method.
public class Mirror {
public <T> T reverse(final T value) {
T result = null;
while (true) {
if (value instanceof String) {
System.out.println("Do for String");
result = value;
break;
}
if (value instanceof Integer) {
System.out.println("Do for Integer");
result = value;
break;
}
if (value instanceof JFrame) {
System.out.println("Do for JFrame");
result = value;
break;
}
throw new RuntimeException("ProgramCheck: Missing handler for type " + value.getClass().getSimpleName());
}
return result;
}
tester:
final Mirror tester = new Mirror();
String s = tester.reverse("string");
Integer i41 = tester.reverse(41);
Integer i42 = tester.reverse(42);
Integer i43 = tester.reverse(43);
JFrame j = tester.reverse(new JFrame());
results:
Do for String
Do for Integer
Do for Integer
Do for Integer
Do for JFrame
You can't bound a generic parameter to range of values. You could however restrict it programatically:
public abstract class AbstractMirror<T> {
T value;
protected AbstractMirror(Class<T> clazz) {
if (clazz != Integer.class && clazz != String.class && clazz != MagicValue.class)
throw new IllegalArgumentException();
}
public abstract T get();
protected abstract T reverse(T value);
}
You can use so-called "witness" types to make the compiler do what you want.
public interface Reversible< T > {
public static final class IntReversible implements Reversible< Integer > {}
public static final class StringReversible implements Reversible< String > {}
public static final class MagicReversible implements Reversible< MagicValue > {}
}
public abstract class Mirror< T, R extends Reversible< T > > {
// ...
}
public class IntMirror extends Mirror< Integer, IntReversible > {
// ...
}
However, the reason your example doesn't make any sense is because you gain virtually nothing from using a generic in this context. What possible algorithm will reverse an integer or a string or a MagicValue without resorting to awful run-time type-checking and casting? The code will be all three reverse algorithms, wrapped with a hideous if-ladder.
So here is the why (worked it out at work)
Generics are always from a subclass, although it looks like
Public class Thing<T> {}
will allow any type in there, really what it's saying is that it will allow any subtype of Object. I.e.
Public class Thing<T extends Object> {}
This is effectively working as inheritance, and indeed, the Oracle Website shows us this happening when the syntactic sugar is removed:
In the following example, the generic Node class uses a bounded type
parameter:
public class Node<T extends Comparable<T>> {
private T data;
private Node<T> next;
public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
public T getData() { return data; }
// ...
}
The Java compiler replaces the bounded type parameter T with the first
bound class, Comparable:
public class Node {
private Comparable data;
private Node next;
public Node(Comparable data, Node next) {
this.data = data;
this.next = next;
}
public Comparable getData() { return data; }
// ...
}
...and so the answer turns out that the reason you can't limit the types in this way is because it effectively turns into multiple Inheritance, which is nasty, and which I'm happy to avoid....
I have a class that i'm uses a generic Type that extends the interface zwave
everything is fine until i try to access a zwave variable for some reason the rm.keyword gives a "NullPointerException". if I cast it to the class scene it works, but that is not what I want
public <T extends zwave> T Find(List<T> Zwave,List<List<String>> listofinputstrings)
{
for(List<String> lst: listofinputstrings)
{
for(String str: lst)
{
for (T rm: Zwave)
{
//*** problem is here
//rm.keyword is always gives a NullPointerException unless i cast it to a class
if (rm.keyword.equals( str.toLowerCase()))
{
return rm;
}
}
}
}
return null;
}
//here is the interface
interface zwave
{
public String keyword="";
public String zwaveID="";
}
//here is a class that implements the interface
public class Scene implements zwave
{
String name;
String keyword;
String zwaveID;
public Scene(String Name,String Keyword,String ZwaveID)
{
name= Name;
zwaveID= ZwaveID;
keyword = Keyword;
}
}
edit
Working code
//search class
public <T extends searchable> T Find(List<T> searchableclasses, List<List<String>> listofinputstrings)
{
for(List<String> lst: listofinputstrings)
{
for(String str: lst)
{
for (T searchable: searchableclasses)
{
for(String key: searchable.GetKeywords())
{
if ( key.equals(str.toLowerCase()))
{
return searchable;
}
}
}
}
}
return null;
}
//abstract class
abstract class searchable
{
String[] keywords; //using array so i can use java's param ability
public List<String> GetKeywords()
{
return new ArrayList(Arrays.asList(keywords));
}
}
//actual class
public class Scene extends searchable
{
String name;
String zwaveID;
public Scene(String Name,String ZwaveID,String... Keywords)
{
name= Name;
zwaveID= ZwaveID;
keywords = Keywords;
}
}
If you don't wanna cast you can do some thing like this:
public <T extends zwave> T Find(List<T> Zwave,List<List<String>> listofinputstrings)
{
for(List<String> lst: listofinputstrings)
{
for(String str: lst)
{
for (T rm: Zwave)
{
if(rm instanceof Scene){
Method method=null;
try {
method = rm.getClass().getMethod("getKeyword");
if ( method.invoke(rm).equals( str.toLowerCase()))
{
return rm;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
return null;
}
NOte:define getKeyword method in Scene class:
I can customize it more with the help of java.lang.reflect. You would not even need to use instance of Scene. But I think you can do it yourself. And hope it will help.
use Reflection API to call at run time.
You need to be using a getter method. When you say rm.keyword, that's referring to a constant (zwave.keyword), which is the empty string. When you cast to Scene, the compiler sees that it's a field and looks it up instead.
Generally, you should make fields like name and keyword private unless you have a specific reason not to and use getter and setter methods to manipulate them.
The variables defined in the interface are final static public even though you didn't explicitly define. When the variable is final, once the value is assigned you cannot reassign it again.
Since you have defined as empty string ("") it will take that value. But you define the variable again in Scene class. So when you cast to Scene object will refer this variable and not the variable in the interface. Otherwise it refers to interface variable.