I can't modify either Class A or Class B. And both Class A & B are huge in size (with several nested Classes and hundreds of parameters). And with multiple threads, memory foot print is impacting the performance.I'm checking all ways to reduce memory usage. Basically I'm trying to limit the scope of Class B instance so that GC can work on it at the earliest.
(For Your Information: I already knew that I can do by B b = new B(); b.setS("Calm Down"); a.setB(b);)
Here is the scenario:
Class A{
private B b;
public getB{return b}
public void setB (B b){this.b = b;}
}
Class B{
private String s;
//getters and setters for s}
Class MyNeed{
A a = new A();
// Here I'm trying to create an obj B and set S and then pass that obj to a.setB().
a.setB (new B().setS("Param S Set"));
}
So I guess that new B() is local to setB(). so in the very next line new B() is out of scope.
But this way in eclipse, I'm getting error that setB() can't accept void. I guess it is setS() returning void.
May be I'm missing some concepts. But I want to have something such simple. How to implement this.
You can try to have a constructor within the class A:
class A{
private B b;
public B getB(){
return b;
}
public void setB (B b){
this.b = b;}
}
public A(S s){
this.S = s;
}
}
So when you do a.setB(), you can just do a.setB(s) and that will set the object S for that A object.
a.setB (new B().setS("Param S Set"));
Ok, That statement starts by creating a new B instance, then it calls the setS method on that instance, passing it the string "Param S Set". Finally, it calls a.setB(...) passing the value returned by the setS() call.
As you already know, that doesn't work because setS() returns void.
May be I'm missing some concepts. But I want to have something such simple. How to implement this.
{
B b = new B();
b.setS("Param S Set");
a.setB(b);
}
What you are trying is wrong. setS() does not return B instance.
You will not save any resources by writing one-liners.
GC will also not clean anything if you set B to A as long as A has a reference to B.
I got it using builder design pattern. Thanks to #Builder by lombok.
Thank you all.
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
I have a problem with an extended class.
This are the classes:
class A{
}
class B extends A{
}
Now the problem is that I have a method that returns A , something like this:
public A doSomthing(){
}
And now I try to do something like this:
public static void main(){
B b = new B();
b = doSomething();
}
But it doesn't seem to work. Is there any way to solve this problem?
The only thing I thought about is it to have something like this:
class B extends A{
public B(A a){
copy all the fields from A to B}
}
And then do:
A a = new A();
a = doSomthing();
B b = new B(a);
Is there a better option?
Fundamentally I think you've missed what the assignment operator does. This statement:
b = doSomething();
changes the value of b to whatever the doSomething() method returns. It doesn't depend on the existing value of b at all. So similarly, when you have:
A a = new A();
a = doSomthing();
... it would make more sense to write:
A a = doSomething();
Now if you need to create an instance of B based on an instance of A, then it may well make sense to write:
A a = doSomething();
B b = new B(a);
or just:
B b = new B(doSomething());
... but you need to understand when existing values are used and when they're not.
Usually I find that when I need to do something like that, it's actually better to use composition than inheritance anyway - that B should have a reference to an existing A rather than extending A. That's certainly something to consider, but without a concrete example we can't say for sure.
You instantiate your object b to be of Type B instead of A therefore polymorphism would not work when calling doSomthing
Change your object b to be of Type A
Java does not have multiple inheritance (c# example) to enforce method signatures. Instead it would make sense to
public static A doSomthing(){
A result = new A();
...
return result;
}
Then you can use:
A a = A.DoSomthing();
B b = (B)A.DoSomthing();
how to use getter setter in two different class
Class A{
int a = 10;
GetterAndSetter gs = new GetterAndSetter();
gs.setValue(a);
}
Class GetterAndSetter {
int a ;
public void setValue(int a){
this.a = a;
}
public int getValue(){
return a;
}
}
class B {
int c;
GetterAndSetter gs = new GetterAndSetter();
c = gs.getValue();
}
While printing c it gives null. And tell me if it is valid or not.
Whenever you write this
GetterAndSetter gs = new GetterAndSetter();
what you're doing is to create a new instance of GetterAndSetter. Two instances that you create won't have any connection between them.
Inside class A, you create a new instance, and set its value. Inside class C, you create a new instance, and read its value. But because you've got two different instances, the value you're reading isn't connected with the value you're setting.
This is roughly like:
I buy an envelope, and put some money inside it.
Later on, I want to get the money back, so I buy a new envelope, and look for the money inside it.
You have to be looking in the same envelope that you put the money in, if you want to find it!
In class A, your code creates a new instance of GetterAndSetter and sets a value to the property. In class B, however, your code creates again another new instance of GetterAndSetter , then gets the value.
The instances your code works with in classes A and B are not the same - hence you don't obtain the values set in A when trying to get it in B. The instance of GetterAndSetter created in B is not used anymore after the code in B exits.
To fix this, you need to pass a reference to the GetterAndSetter instance from class A to B. You can do this e.g. by passing it as a parameter to a method of B, or by creating a new instance of A in B and calling a method that provides an instance of GetterAndSetter.
An example of the first option (pass as parameter):
Class A{
...
GetterAndSetter createAndSet();
int a = 10;
GetterAndSetter gs = new GetterAndSetter();
gs.setValue(a);
return gs;
}
...
}
class B {
...
void getValueFromGetterAndSetter(GetterAndSetter gs) {
int c;
c = gs.getValue();
...
}
...
}
To connect the instances, we of course also need to have another piece of code (assuming instances of A and B exist already):
...
b.getValueFromGetterAndSetter(a.createAndSet());
...
You have used different reference. You should use same reference so that only you can access the value.
you need to understand the basics of oops, you have created one instance inside class A and you are trying to access in Class B which is possible only if you pass the reference of that object from Class A to B. In that case you have to have the instance of GetterAndSetter which you have created in Class A in Class B, instead you have created another new instance which will create new reference in memory, and the class variable a will be null.
In your code, both class A and B create new objects for GetterAndSetter. Hence they are not shared between these classes. Thats why you are getting null.
I wounder how your code print null for C. I think it would be "0" instead.
It is valid, here is what happens:
You create object gs in class A
Then you set the value of a of that object to 10
You then create another object gs in class B
Last but not least, you ask the object gs from class B what its value for a is.
Guess what, its NULL as you did not set its value anywhere so it wont return one.
I got a class Foo having a method doSomething that uses two class-related variables b and c that are expensive to get/create. My first version looks like this:
public class Foo {
private final A a;
public Foo(A a) {
this.a = a;
}
public void doSomething() {
final B b = a.getB();
final C c = b.getC();
for (int i = 0; i < 1000; i++) {
// do something with b and c
}
}
}
So I get the first object (type B) via a class variable a and the second object (type C) via the first object.
Now, since those variables are related to the class and the method is always called exactly one time (though not necessarily when creating an object of type Foo), I thought about making them class variables as well:
public class Foo {
private final A a;
private final B b;
private final C c;
public Foo(A a) {
this.a = a;
b = a.getB();
c = b.getC();
}
public void doSomething() {
for (int i = 0; i < 1000; i++) {
// do something with b and c
}
}
}
I'm not sure which version to use if any of those two. I somehow don't feel comfortable making those two variables class members since they can be retrieved from the existing class variable a. However, it would increase readability of the methods IMO.
You are absolutely right. If it increases readability, bu all means do it. However, I would ask you this: What is the purpose of Referencing A from within the class? Is it only for getting B and C?
In this case, I would just input B and C in Foo's constructor!
This way you even make it more readable by breaking the dependency on A and Making the dependency on B and C more explicit.
Also, consider whether you are using these variables in other methods in the class. If the answer is yes- it signals that they should be class members, However, if the class contains a lot of methods that do not use these variables, that might signal the opposite.
The general principle you should follow here is the principle of High Cohesion
generally speaking, if you can use a local variable, it is preferable to using a field.
Using a local variable
limits the variable to where it is used.
uses less memory.
is thread safe.
Why not just store instances of B and C in your class Foo? Do you reference A somewhere in your class? Otherwise, Storing both B and C as instance variables is no less memory efficient, since storing one A object contains a B and C object.
From my experience static (or class variable|field|method) usually became evil after some time and needs to be refactorred out except cases when this stuff is static by it's nature (Math.PI or Math.max() are examples or such static things). If those methods are doing some computation based on anything dynamic I would leave them as instance.
I have a real weird problem.
(Very important note: this is an example cause I can't paste the original code, I wrote it as text with no compiler.) I have 2 classes:
class B {
private int num = 9;
public int getNum(){
return num;
}
public void setNum(int num){
this.num = num;
}
}
class A {
private B b = new B();
public void setB(B b){
b.setNum(b != null? b.getNum() : 8);
}
public B getB(){
if (b == null)
System.out.println("How possible?");
return b;
}
}
Now, sometimes I get the print... but I don't see how's that possible.
A is a serialized class, but yet I can't figure it out.
It's not possible, no. You'll get a type error in the definition of A.getB() when you try to compile it, and your definition of A.setB() looks dubious as well (shadows b).
There are a few circumstances in which b might be null:
reflection. b might be set to null reflectively, which circumvents your setter.
custom serialisation. b might be explicitly restored as null. Alternatively, if B is not serialisable, you have it marked as transient to avoid errors and it's not restored.
To verify a simple serialisation workflow, use the following code:
Object object = "someString";
ByteArrayOutputStream holder = new ByteArrayOutputStream();
new ObjectOutputStream(holder).writeObject(object);
Object readObject = new ObjectInputStream(new ByteArrayInputStream(holder.toByteArray())).readObject();
System.out.println(readObject);
where the first line is replaced by the actual object you wish to test
If you manage to serialize an instance of A which has b == null, then you get a NPE. The reason is that during de-serialization, the constructor isn't invoked and therefore, private B b = new B(); isn't run, so b stays null.
Did you serialize the instance of A before adding the initialization of B to the class?
If that is the case you could get an instance of A where b is null because the constructors are not called (initializing a member of the class is part of the implicit constructor).
Then you will need to add an implementation of readObject() to class A there you can check whether or not b is null and initialize it if necessary.
This line won't compile either:
b.setNum(b != null? b.getNum : new B());
Well, what about this? If you give B as a parameter, why not use it?
class A {
private B b = new B();
public void setB(B b){
if(b != null) {
this.b = b;
}
}
public B getB(){
return b;
}
}
Just an idea: replace
System.out.println("How possible?");
with
new Exception().printStackTrace();
That should make it easier for you to see what happened just before. Otherwise, without more information, the only things that seems a possible cause is the serialization.