I have 2 different classes with different fields and a class which has all the fields of both classes. Is there any way to cast the object in to two separate objects?
class A{
private int a;
private int b;
}
class B{
private int a;
private int b;
}
If object D have all the properties of A and B classes, Is there any way to cast them separately?
Casting take place from child to parent (downcast) or vise versa (upcast):
class A extends B
B b = (B)(new A());
or in case of interfaces:
List<String> myList = new ArrayList<>();
ArrayList<String> myArrayList = (ArrayList)myList;
Be careful when casting - if casting is not possible, you'll receive Exception!
In your case, mapping is what you're looking for. You simply need a mapper.
For example:
public class AToBMapper {
public static A fromB(B b) {
A a = new A();
a.setA(b.getA());
a.setB(b.getB());
return a;
}
public static B fromA(A a) {
//fill in
}
}
As complement of the very good answer of xenteros, you could also use library to do it if you have to repeat this task for many classes.
Spring, apache-commons and many others provides utility class to copy field by field which one of them that have the same name and type between two classes:
For example with ModelMapper :
ModelMapper mapper = new ModelMapper();
A a = new A(....);
B b = mapper.map(a, B.class)
Some libraries are very efficient (Selma, MapStruct, JMapper). Most of them generating the code at compile time
Others are less efficient.
You should so evaluate this point, the size of objects to map and the mapping frequency before generalizing the use of this kind of library.
Related
public class A {
private String superStr;
public String getSuperStr() {
return superStr;
}
public void setSuperStr(String superStr) {
this.superStr = superStr;
}
}
public class B extends A {
private String subStr;
public String getSubStr() {
return subStr;
}
public void setSubStr(String subStr) {
this.subStr = subStr;
}
}
And I expect result likes below
public static void main(String[] args) {
A a = fuc();
B b = new B();
b = (B) a;
b.setSubStr("subStr");
System.out.println(a.getSuperStr() + b.getSubStr());
}
private static A fuc() {
A a = new A();
a.setSuperStr("super");
return a;
}
but java.lang.ClassCastException is ocuured.
How can I cast this?
I want use subclass variable and super class variable.
thank you
How can I cast this?
You can't. You can only cast when the object in question has an "is a" relationship with the type. In your case, you have an A object (the one from fn), which is not a B. (All B objects are As, because B extends A, but not all A objects are Bs.)
Consider: Let's call B Bird and A Animal: A Bird is an Animal, but not all Animals are Birds. So we can treat all Birds as Animals, but we cannot treat all Animals as Birds. When you're using a variable of a given type to refer to an object, you're treating the object as being of that type (e.g., B b = (B)a tries to treat the Animal a as a Bird).
Side note: There's no point to the indicated part of the code:
B b = new B();
// ^^^^^^^^^^
b = (B) a;
Since the very next line assigns to b (well, it would if it would compile), there's no purpose served by doing new B() and assigning that to b just beforehand. (Unless the B constructor has side-effects, which is generally a Bad Idea™.)
Casting a particular object to another types does not magically convert it into an instance of that class (or at least not in Java); Therefore, the object referenced by variable a does not e.g. have the field subStr to use despite that the object referenced by b after executing B b = new B(); does.
The others have already explained why you can't do that. I'm here to give you a simple alternative. Your B class could have a constructor that had an A as argument and you would simply wrap that A so you could "transform" it to a B. Using that your code would look way more clean, it would actually work and you were following a good design pattern. For more information check the Decorator Pattern
More specific about the question:
//There're two classes A and B:
Class A {
public static List<B> b = new ArrayList<B>();
}
Class B {
}
In my schema, I want to an object b from Class B. Then under all circumstances,object b will involve at least two objects "a_x" and "a_y" from Class A. How can I create such a relationship?
First thing,This public static List<B> b = new List<B>(); wont compile.
You might need public static List<B> b = new ArrayList<B>();
You cannot instantiate an Interface.So provide an concreate implementation.Ex:ArrayList
And second thing,You should add them directly where ever your are creating this list.
This is the relationship:
class A
{
public List<B> b = new ArrayList<B>();
}
class B
{
A ax;
A ay;
B(A ax, A ay)
{
this.ax = ax;
this.ay = ay;
}
}
This is what you need?
Why do you need such relantioship?
If you have a relation where each B is related to at least two A instances, then B needs a collection-typed field. For example:
public class B {
private List<A> relatedAList = new ArrayList<>();
...
}
This needs to be an instance field, not a static field.
But if you have a 2+ relationship, it doesn't make sense to call the related objects x and y ... because what if there is a z, and a p and so on. Unless there is a fixed upper bound on the number of related A objects for each B, you have to use some kind of collection to represent each B's related As.
I've a concrete class A that implements an interface B.
B ref = new A();
Code :
public interface B{
public abstract String[] getWords();
}
public class A implements B {
private String[] words = new String[] {};
public void setWords(String[] words){
this.words = words;
}
public String[] getWords(){
return this.words;
}
}
In the interface B, I've only getter method but no setter method though the class A has it.
So when I do this : B ref = new A();, will this code work and how will I set words?
You won't be able to call setWords on ref if it is defined as B ref = ....
This is one of the cases where you need to use the exact type when declaring the variable (or use a cast):
A ref = new A();
Alternatively:
you could create an interface C that extends B and contains both methods and have A implement C.
you could provide a constructor in A that takes a String[] words argument to initialise your words field, and not provide a setter at all.
I would personally favour the latter option:
public class A implements B {
private final String[] words;
public A(String[] words) {
this.words = words;
}
public String[] getWords() {
return this.words;
}
}
So when I do this : B ref = new A();, will this code work...
Yes, it will.
...and how will I set words?
You won't be able to unless you:
make A's constructor take the list of words; or
add setWords() to B; or
keep a reference of type A to your object; or
downcast ref to A.
Of these, I would go with one of options 1-3. The last option is only included for completeness.
You have to cast back to the original type if the interface does expose it
if (ref instanceof A)
((A) ref).setWords(words);
else
// something else.
A better solution is to add the method to the interface.
B ref = new A();//1
ref.setWords(whatever);//2
The above code wouldn't compile as setWords() is not defined in your interface B, you'd get a compiler error on line 2.
as other have already expressed in their answers. you got 2 options as work arounds
Create object as A ref = A();
Downcast the ref to A type like ((A)ref).setWords(watever);
So when I do this : B ref = new A();, will this code work
Yes
and how will I set words?
You cannot. You need to have setter method in your interface.
Between you don't need to define method as abstract. It is by default abstract.
HashMap
public Map<String, BarrackData> barrack = new HashMap<String, BarrackData>();
BarrackData.java
public class BarrackData {
int A;
int B;
int C;
int D;
int E;
String Title;
public BarrackData(int a, int b, int c, int d, int e, String title) {
A = a;
B = b;
C = c;
D = d;
P = p;
Title = title;
}
How can I save this HashMap?
And load it?
I tried different methodes with Objectin/outputstream,
it ended up with NotSerializable, ObjectSteam and IO exception,
Where i have no clue how to deal with them.
Only Serializable classes may be serialized: Just add implements Serializable to your class:
public class BarrackData implements Serializable {
Note that to actually be serialized, all fields within the class must be Serializable, however java primitives, arrays (if the element type is Serializable), java.lang classes (like String) and Collections (if the element type is Serializable) are Serializable, so you're OK.
To complete answers, pay attention to the fact that the outcome of keySet() belonging to HashMap (if you need it at any time) is not Serializable.
Indeed, keys aren't supposed to be dissociated from values concerning an HashMap.
You must make your Object class serializable (give it serialize() and deserialize() methods which convert it to/from a string or some such that can be saved/loaded). Apparently, HashMaps facilitate some level of serialization out of the box.
Here is a link to a tutorial on Java serialization: http://www.tutorialspoint.com/java/java_serialization.htm
and here is some more detailed info on HashMap serialization:
Serializing and deserializing a map with key as string
As Bohemian mentioned, implementing Serializable is the standard way to do this.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I copy an object in Java?
How can I initialize an object (say A) in java and set its initial member values equal to a second object (say B). After initialization I want to modify the members of A without modifying the members of B. So at initialization of A I only want to copy the data of B. How is this done in a nice way??
You could implement and use clone
MyClass b = new MyClass();
MyClass a = b.clone();
Note: some classes are not Cloneable, or have broken implementations. e.g. only have a shallow copy when they should be a deep copy.
If the class is Serializable you can serialize it and deserialize it in memory. Not exactly nice but it works.
Or you could create your own "copy" constructor.
One possible solution for that would be implement clone method on your class and use clone as follows:
MyClass a = new MyClass();
MyClass b = a;
You will notice that clone() isn't really a public method, so your will need to expose it. Additionally you need to tell Java that your object is Cloneable (this is done making your class implement Cloneable). The following code ilustrate it:
public class MyClass implements Cloneable {
#Override
protected MyClass clone() throws CloneNotSupportedException {
return (MyClass)super.clone();
}
}
That all depends on the type of the members. I'll give an Example:
class A
{
public float value;
public int[] anArray;
public A(B b)
{
//primitive may be assigned directly.
this.value = b.value;
// other types different approaches:
//copy the contents of the array
this.anArray = new int[b.anArray.length];
System.arraycopy(b.anArray, 0, this.anArray, 0, b.anArray.length);
}
}
class B
{
float value;
int[] anArray;
public B(int size)
{
this.value = 3f;
this.anArray = new int[size];
for (int i = size - 1; i >= 0; i--)
{
this.anArray[i] = i * 10;
}
}
}
B b = new B(5);
A a = new A(b);
Cloning is a straightforward option for copying. If you ever want to do something where you need more control, create your own method that performs your copy exactly how you need it:
public MyType copy()
{
MyType a = new MyType();
// Initialize how you need to here, use the object this was called from if you'd like
a.property = this.property;
// etc.
return a;
}
This gives you more direct control, but takes more time to code. If clone will suit your purposes, stick to that.
EDIT: I am going to give an example based on your comments on this answer.
Let us assume we have the following types:
TypeA: has the following member variables
int number = 5; // Default value built in by constructor.
int letter = 'x'; // Value is 'a' when constructed but has been changed.
ArrayList<TypeB> list = {b1, b2, b3} // All are initialized.
TypeB: has the following member variables
double decimal = 5.32
TypeC someObject = ...
TypeC: has some stuff, but we are going to ignore it.
Now, When we want to copy TypeA, we must do the following:
Copy over the number and character directly as they are value types.
Copy over a reference to the ArrayList which contains a reference to some TypeBs.
Luckily those are easy steps.
int copyNumber = this.number;
char copyChar = this.letter;
ArrayList<TypeB> copyList = this.list;
return new TypeA(copyNumber, copyChar, copyList);
Now that assumes a particular constructor that takes those three arguments, but hopefully you get the idea.
It would get tricky if you wanted to just get values, not references to all of the TypeBs in the ArrayList. You would have to loop through the ArrayList and create new TypeBs that copied all of ITS values (double and TypeC objects as either references or values...)
In short, what you want is an easier copy to perform. Simple assignment operators copy values with primitive types and references with Objects.