A few questions:
When I do casting while reading an object.... why I have to use B o_b = (B) one; and why not A o_b = (A) one? Object type is A which I have saved in a file. Also, I want to confirm that when we make an object
like this A a = new B() what is object type in this line?
Moreover, why doesn't the class get saved using an object ?
Why it's not preferable to make static variables to be saved (serializable)?
Code:
import java.io.*;
class A {
public void go(int height){
}
}
public class B extends A implements Serializable{
int height;
public void go(int height){
this.height = height;
System.out.println("height is" + height);
}
public static void main(String[] args){
A a = new B();
a.go(43);
//Saving Object
try{
FileOutputStream f = new FileOutputStream("foo.ser");
ObjectOutputStream o = new ObjectOutputStream(f);
o.writeObject(a);
o.close();
// Reading an Object
FileInputStream filestream = new FileInputStream("foo.ser");
ObjectInputStream p = new ObjectIntputStream(filestream);
Object one = p.readObject();
//Casting
B o_b = (B) one;
p.close();
System.out.println("saved values were" + o_b.height);
} catch (Exception ex){
ex.printStackTrace();
}
}
}
Lets look at what's the type at A a = new B() first. The static type of the variable a is A while the dynamic type is B. So while you use a as if it was of type A in your code it points to an object of type B at runtime. You might want to read up on polymorphism. This also explains why you can cast your deserialized object to B although you serialized a. The object that was acctually serialized was of type B. You could change your initialization of a to A a = new A() and the cast would fail at runtime. Also you should already be getting a compiler warning for an unchecked cast, which basically means it cannot be ensured that the cast suceeds at runtime.
You could also serialize so called class objects. With Class<A> classA = A.getClass() you would have get the class object for class A and would be able to serialize it.
You are serializing instances. A static variable is not part of an instances, it belongs to the class the instances where created from. I think you could serialize static variables by serializing the class object (see 2.) but I'm not sure about that.
I hope this answers your questions. Keep in mind that not everything that can be done should be done. I would consider serializing a class object bad design. There is certainly a better way to persist the content of static variables.
Related
I was looking as the question : Instantiate a class from its string name which describes how to instantiate a class when having its name. Is there a way to do it in Java? I will have the package name and class name and I need to be able to create an object having that particular name.
Two ways:
Method 1 - only for classes having a no-arg constructor
If your class has a no-arg constructor, you can get a Class object using Class.forName() and use the newInstance() method to create an instance (though beware that this method is often considered evil because it can defeat Java's checked exceptions).
For example:
Class<?> clazz = Class.forName("java.util.Date");
Object date = clazz.newInstance();
Method 2
An alternative safer approach which also works if the class doesn't have any no-arg constructors is to query your class object to get its Constructor object and call a newInstance() method on this object:
Class<?> clazz = Class.forName("com.foo.MyClass");
Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
Object instance = constructor.newInstance("stringparam", 42);
Both methods are known as reflection. You will typically have to catch the various exceptions which can occur, including things like:
the JVM can't find or can't load your class
the class you're trying to instantiate doesn't have the right sort of constructors
the constructor itself threw an exception
the constructor you're trying to invoke isn't public
a security manager has been installed and is preventing reflection from occurring
MyClass myInstance = (MyClass) Class.forName("MyClass").newInstance();
Using newInstance() directly is deprecated as of Java 8. You need to use Class.getDeclaredConstructor(...).newInstance(...) with the corresponding exceptions.
To make it easier to get the fully qualified name of a class in order to create an instance using Class.forName(...), one could use the Class.getName() method. Something like:
class ObjectMaker {
// Constructor, fields, initialization, etc...
public Object makeObject(Class<?> clazz) {
Object o = null;
try {
o = Class.forName(clazz.getName()).newInstance();
} catch (ClassNotFoundException e) {
// There may be other exceptions to throw here,
// but I'm writing this from memory.
e.printStackTrace();
}
return o;
}
}
Then you can cast the object you get back to whatever class you pass to makeObject(...):
Data d = (Data) objectMaker.makeObject(Data.class);
use Class.forName("String name of class").newInstance();
Class.forName("A").newInstance();
This will cause class named A initialized.
Use java reflection
Creating New Objects
There is no equivalent to method invocation for constructors, because invoking a constructor is equivalent to creating a new object (to be the most precise, creating a new object involves both memory allocation and object construction). So the nearest equivalent to the previous example is to say:
import java.lang.reflect.*;
public class constructor2 {
public constructor2()
{
}
public constructor2(int a, int b)
{
System.out.println(
"a = " + a + " b = " + b);
}
public static void main(String args[])
{
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct
= cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
which finds a constructor that handles the specified parameter types and invokes it, to create a new instance of the object. The value of this approach is that it's purely dynamic, with constructor lookup and invocation at execution time, rather than at compilation time.
Class.forName("ClassName") will solve your purpose.
Class class1 = Class.forName(ClassName);
Object object1 = class1.newInstance();
String str = (String)Class.forName("java.lang.String").newInstance();
something like this should work...
String name = "Test2";//Name of the class
Class myClass = Class.forName(name);
Object o = myClass.newInstance();
i have a class that is used widely in my project as some sort of field holder. Something like:
class A
{
private String field = null;
private String field2 = null;
private String field3 = null;
// and its generic Getters and Setters
}
In certain part of code i need add additional fields to this class. So i did this
class B extends A
{
private String fieldInB = null;
// and its Getters and Setters
}
in my function i thought i could easily do
public void foo( A a )
{
B b = (B)a;
}
And i could have all the fields written in aobject and i could easily set only field in b and use it. This seams like a common problem, but i just don't know how to do it except with an very ugly approach:
public B( A a )
{
// copy all the fields one at the time
}
You areconfusing different parts of Java:
B b = (B)a;
this is classical class cast, but to work with B class object you need:
1. be sure that a is of B class (check it with instanceof java keyword:
if (a instanceof B) {
B b = (B) a;
}
2. or wrap a in B class object (create B class object with copying fields from a).
PS in most of Java coding conventions it is recommended to fill fields by concrete values only (and not fill with default JavaVM values - nulls)
Comfortable way to copy A class fields to new instance:
public A (A a) {
this.field = a.field;
this.field2 = a.field2;
this.field3 = a.field3;
}
and for B class:
public B (A a) {
super(a);
}
Another way - some libraries that will work with A class and B class as with beans. Sample of this libraries you can find in Toilal's answer
You could use Dozer. It allows to map bean property values from one bean class to another.
Hai john Actually i didn't get your exact requirement. I recon the way you have written this code is not right.
Private variable cant be inherited.If you need to extend values to your subclass you should have declared those variables as public.
public B(A a)
{
super.field=a.field;
super.field2=a.field2;
super.field3=a.field3;
}
I was looking as the question : Instantiate a class from its string name which describes how to instantiate a class when having its name. Is there a way to do it in Java? I will have the package name and class name and I need to be able to create an object having that particular name.
Two ways:
Method 1 - only for classes having a no-arg constructor
If your class has a no-arg constructor, you can get a Class object using Class.forName() and use the newInstance() method to create an instance (though beware that this method is often considered evil because it can defeat Java's checked exceptions).
For example:
Class<?> clazz = Class.forName("java.util.Date");
Object date = clazz.newInstance();
Method 2
An alternative safer approach which also works if the class doesn't have any no-arg constructors is to query your class object to get its Constructor object and call a newInstance() method on this object:
Class<?> clazz = Class.forName("com.foo.MyClass");
Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
Object instance = constructor.newInstance("stringparam", 42);
Both methods are known as reflection. You will typically have to catch the various exceptions which can occur, including things like:
the JVM can't find or can't load your class
the class you're trying to instantiate doesn't have the right sort of constructors
the constructor itself threw an exception
the constructor you're trying to invoke isn't public
a security manager has been installed and is preventing reflection from occurring
MyClass myInstance = (MyClass) Class.forName("MyClass").newInstance();
Using newInstance() directly is deprecated as of Java 8. You need to use Class.getDeclaredConstructor(...).newInstance(...) with the corresponding exceptions.
To make it easier to get the fully qualified name of a class in order to create an instance using Class.forName(...), one could use the Class.getName() method. Something like:
class ObjectMaker {
// Constructor, fields, initialization, etc...
public Object makeObject(Class<?> clazz) {
Object o = null;
try {
o = Class.forName(clazz.getName()).newInstance();
} catch (ClassNotFoundException e) {
// There may be other exceptions to throw here,
// but I'm writing this from memory.
e.printStackTrace();
}
return o;
}
}
Then you can cast the object you get back to whatever class you pass to makeObject(...):
Data d = (Data) objectMaker.makeObject(Data.class);
use Class.forName("String name of class").newInstance();
Class.forName("A").newInstance();
This will cause class named A initialized.
Use java reflection
Creating New Objects
There is no equivalent to method invocation for constructors, because invoking a constructor is equivalent to creating a new object (to be the most precise, creating a new object involves both memory allocation and object construction). So the nearest equivalent to the previous example is to say:
import java.lang.reflect.*;
public class constructor2 {
public constructor2()
{
}
public constructor2(int a, int b)
{
System.out.println(
"a = " + a + " b = " + b);
}
public static void main(String args[])
{
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct
= cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
which finds a constructor that handles the specified parameter types and invokes it, to create a new instance of the object. The value of this approach is that it's purely dynamic, with constructor lookup and invocation at execution time, rather than at compilation time.
Class.forName("ClassName") will solve your purpose.
Class class1 = Class.forName(ClassName);
Object object1 = class1.newInstance();
String str = (String)Class.forName("java.lang.String").newInstance();
something like this should work...
String name = "Test2";//Name of the class
Class myClass = Class.forName(name);
Object o = myClass.newInstance();
I have two (sibling) classes, both is subclass of the same parent. Parent contains all the methods that is shared by the two sibling, and the sibling classes contain only methods that are not shared and has different implementations.
Example,
class Parent() {
}
class Sibling1 extends Parent() {
byte[] sharedSecret;
int sharedSecretLength;
public generateKey() {
sharedSecret = keyAgree.generateSecret());
sharedSecretLength = sharedSecret.length);
}
}
class Sibling2 extends Parent() {
byte[] sharedSecret2;
int sharedSecretLength2;
public generateKey() {
sharedSecret2 = new byte[sharedSecretLength];
sharedSecretLength2 = keyAgree.generateSecret(sharedSecret2, 0);
}
public int getSharedSecretLength() {
return sharedSecretLength();
}
}
As you can see, both contains same method but implemented differently. My question is, if objects of both class (sibling1 and sibling2) are created AND obj2 generateKey to be generated successfully depends on sharedSecretLength of obj1. Example,
Parent obj1 = new Sibling1();
Parent obj2 = new Sibling2();
obj1 is instantiated in different class (Server class that I created) and obj2 in different class (Client that I created). If obj1 invoke it's own generateKey --> ((Sibling1)obj1).generateKey(), how can I use use getSharedSecretLength on the same object (obj1) to relay the needed information over to obj2's generateKey to generate successfully? I tried something like (in obj2's generateKey() ):
sharedSecret2 = new byte[Sibling1.sharedSecretLength];
...and it didn't work. Creating Sibling1 obj1 inside of Sibling2 class and then call it that way, for example,
Sibling1 xx = null;
.
.
sharedSecret2 = new byte[((Sibling1)xx).sharedSecretLength];
doesn't work because xx is new object. I am trying to use the old obj in which it generated it's key and contains sharedSecretLength that is not 0
If both obj1 and obj2 were created in the same class, it would have been easier.
Please help point me to the right direction
Instead of
((Sibling1)xx).sharedSecretLength
call it like
((Sibling1)xx).getSharedSecretLength()
In java, you have pass the empty parenthesis if it doesn't accept parameter and it doesnt work by field name, you will have to give the same method name as to what you have defined.
It sounds like you should refactor like this so that the generateKey method on Sibling2 has the argument it requires:
Sibling1 obj1 = new Sibling1();
obj1.generateKey();
Siblibg2 obj2 = new Sibling2();
obj2.generateKey(obj1.getSharedSecretLength());
I was looking as the question : Instantiate a class from its string name which describes how to instantiate a class when having its name. Is there a way to do it in Java? I will have the package name and class name and I need to be able to create an object having that particular name.
Two ways:
Method 1 - only for classes having a no-arg constructor
If your class has a no-arg constructor, you can get a Class object using Class.forName() and use the newInstance() method to create an instance (though beware that this method is often considered evil because it can defeat Java's checked exceptions).
For example:
Class<?> clazz = Class.forName("java.util.Date");
Object date = clazz.newInstance();
Method 2
An alternative safer approach which also works if the class doesn't have any no-arg constructors is to query your class object to get its Constructor object and call a newInstance() method on this object:
Class<?> clazz = Class.forName("com.foo.MyClass");
Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
Object instance = constructor.newInstance("stringparam", 42);
Both methods are known as reflection. You will typically have to catch the various exceptions which can occur, including things like:
the JVM can't find or can't load your class
the class you're trying to instantiate doesn't have the right sort of constructors
the constructor itself threw an exception
the constructor you're trying to invoke isn't public
a security manager has been installed and is preventing reflection from occurring
MyClass myInstance = (MyClass) Class.forName("MyClass").newInstance();
Using newInstance() directly is deprecated as of Java 8. You need to use Class.getDeclaredConstructor(...).newInstance(...) with the corresponding exceptions.
To make it easier to get the fully qualified name of a class in order to create an instance using Class.forName(...), one could use the Class.getName() method. Something like:
class ObjectMaker {
// Constructor, fields, initialization, etc...
public Object makeObject(Class<?> clazz) {
Object o = null;
try {
o = Class.forName(clazz.getName()).newInstance();
} catch (ClassNotFoundException e) {
// There may be other exceptions to throw here,
// but I'm writing this from memory.
e.printStackTrace();
}
return o;
}
}
Then you can cast the object you get back to whatever class you pass to makeObject(...):
Data d = (Data) objectMaker.makeObject(Data.class);
use Class.forName("String name of class").newInstance();
Class.forName("A").newInstance();
This will cause class named A initialized.
Use java reflection
Creating New Objects
There is no equivalent to method invocation for constructors, because invoking a constructor is equivalent to creating a new object (to be the most precise, creating a new object involves both memory allocation and object construction). So the nearest equivalent to the previous example is to say:
import java.lang.reflect.*;
public class constructor2 {
public constructor2()
{
}
public constructor2(int a, int b)
{
System.out.println(
"a = " + a + " b = " + b);
}
public static void main(String args[])
{
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct
= cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
}
catch (Throwable e) {
System.err.println(e);
}
}
}
which finds a constructor that handles the specified parameter types and invokes it, to create a new instance of the object. The value of this approach is that it's purely dynamic, with constructor lookup and invocation at execution time, rather than at compilation time.
Class.forName("ClassName") will solve your purpose.
Class class1 = Class.forName(ClassName);
Object object1 = class1.newInstance();
String str = (String)Class.forName("java.lang.String").newInstance();
something like this should work...
String name = "Test2";//Name of the class
Class myClass = Class.forName(name);
Object o = myClass.newInstance();