I have this scenario:
class ClassB{
ClassB(){
ClassA a = new ClassA(() -> a.foo());
}
}
class ClassA{
ClassA(Runnable onChange) {
}
public void foo(){
System.out.println("Hello");
}
}
And I get "Variable 'a' might not have been initialized". I understand why this is happening. Is there a work around or do I have to restructure my classes?
Without changing any of your types, this should work:
class ClassB {
ClassB() {
AtomicReference<A> ref = new AtomicReference<>(); // holder for instance
ClassA a = new ClassA(() -> ref.get().foo());
ref.set(a);
}
}
But you cannot invoke your lambda (Runnable#run) in your constructor, because a still has the value null. Only after the constructor has completed, the value is assigned.
Another possibility could be using a Consumer instead of a Runnable:
class ClassB {
ClassB() {
ClassA a = new ClassA(that -> that.foo()); // or maybe even: A::foo
}
}
class ClassA {
ClassA(Consumer<A> onChange) {
}
public void foo() {
System.out.println("Hello");
}
}
// call outside of `A`:
consumer.accept(a);
// or, inside of `A`:
consumer.accept(this);
Without seeing the rest of the code, it is difficult to give a good solution.
I think you should consider refactoring your code and use a different approach.
It's hard to tell without the full code but I suspect the design is not optimal.
With that said, here is something you could do which is similar to your approach.
Make ClassA Runnable and abstract:
abstract class ClassA implements Runnable{
private final Runnable onChange;
protected ClassA() {
this.onChange = this;
}
public void foo(){
System.out.println("Hello");
}
}
In ClassB you can implement an anonymous ClassA:
class ClassB {
ClassB() {
ClassA a = new ClassA() {
#Override
public void run() {
foo();
}
};
}
}
Related
I have 2 classes, and I have made one class (Class A) instantiate a Class B object.
I have a method in Class B that I want to call a method in Class A.
I'm working on a larger project for practicing Java, so I am simplifying things here.
// Class A:
public class ClassA {
private int number;
private ClassB instanceOfB = new ClassB();
public ClassA {
number = 0;
}
public void incrementNumber {
number++;
}
public void incrementNumberLongWay {
instanceOfB.incrementNumberInA()
}
}
// Class B:
public class ClassB {
public void incrementNumberInA() {
// My desire: Call Class A's incrementNumber method
// What should I put here?
}
}
How do I make sure incrementNumberLongWay works? Class A has been instantiated, and it's method incrementNumberLongWay is called, so this should call ClassB's method incrementNumberInA
I know this seems extremely convoluted, but the reason I'm doing this, is because in my program I'm not incrementing numbers, but instead doing some logic in Class B, and only wanting to affect Class A in certain cases.
You can't do this with the code provided. Relationships are by default one way. B doesn't know about A so cannot access it.
What you can do is pass a reference of A to B in it's construction process and then access A via that reference.
One solution would be to pass a method of A as a callback.
For example:
public class ClassA {
private int number;
private ClassB instanceOfB = new ClassB();
public ClassA {
number = 0;
}
public void incrementNumber {
number++;
}
public void incrementNumberLongWay {
instanceOfB.incrementNumberInA(this::increment);
// alternatively
// instanceOfB.incrementNumberInA(() -> incrementNumber());
}
}
public class ClassB {
public void incrementNumberInA(Runnable callbackMethod) {
callbackMethod.run();
}
}
This removes B's dependency on A, and instead allows a general callback mechanism.
However, for such a simple scenario this approach isn't advised.
It's probably a bad idea in general to have a circular dependency in this way. One approach to break the cycle would be to have a third class (classC?) that implements the increment logic (or whatever your real-world equivalent is), and have classA and classB instances each reference classC. That way there's no case where two classes know about each other.
ClassB doesn't know anything about ClassA. So, you couldn't do it.
The ugly decision is
public void incrementNumberLongWay() {
instanceOfB.incrementNumberInA(this);
}
and in
public class ClassB {
public void incrementNumberInA(ClassA cl) {
cl.incrementNumber();
}
}
You can't call methods from class A from class B as class B has no reference to an object of class a. You could, however, pass class A's current number state to class B as parameter, and return a value from class B which class A can then get and use.
For example:
public class A {
private int number;
public A(int number) {
this.number = number;
}
public void incrementNumber(boolean largeIncrement) {
if(largeIncrement) {
B bInstance = new this.B();
number = bInstance.incrementNumberLongWay(number);
}
else {
number++;
}
}
private class B {
private B() {
// if some initialization is needed...
}
public int incrementNumberLongWay(int num) {
num += 1000;
return num;
}
}
}
Hope this is what you wanted.
Im very new to programming and want to know if I can somehow get the object from a class where I already used new MyClass(); to use it in another class and that I don't need to use new MyClass(); again. Hope you get the point.
Some very simple example:
class MyFirstClass
{
Something st = new Something();
}
class Something()
{
// some code
}
class MySecondClass
{
// This is where I want to use the object from class Something()
// like
getObjectFromClass()
}
You can use Singleton pattern to achieve this
This is kickoff example of such object. It has a private constructor and public class method getInstance:
static methods, which have the static modifier in their declarations,
should be invoked with the class name, without the need for creating
an instance of the class
When we make a call to getInstance it checks if an object has been created already and will return an instance of already created objected, if it wasn't created it will create a new object and return it.
public class SingletonObject {
private static int instantiationCounter = 0; //we use this class variable to count how many times this object was instantiated
private static volatile SingletonObject instance;
private SingletonObject() {
instantiationCounter++;
}
public static SingletonObject getInstance() {
if (instance == null ) {
instance = new SingletonObject();
}
return instance;
}
public int getInstantiationCounter(){
return instantiationCounter;
}
}
To check how does this work you can use the following code:
public static void main(String[] args) {
SingletonObject object = SingletonObject.getInstance();
System.out.println("Object was instantiated: " + object.getInstantiationCounter() + " times.");
object = SingletonObject.getInstance();
System.out.println("Object was instantiated: " + object.getInstantiationCounter() + " times.");
object = SingletonObject.getInstance();
System.out.println("Object was instantiated: " + object.getInstantiationCounter() + " times.");
}
Since you have just started coding won't give you a term like reflection and all.. here is one of the simple way is have a public getter() method.
Consider this simple example
class Something {
private int a=10;
public int getA() {
return a;
}
}
Here is the First which has a public method which return the object that i created in this class for the Something Class
class MyFirstClass {
private Something st;
public MyFirstClass() {
this.st = new Something();
}
public Something getSt() {
return st;
}
}
Accessing it from another Class
class MySecondClass {
public static void main(String...strings ){
MyFirstClass my =new MyFirstClass();
System.out.println(my.getSt().getA());
}
}
Output: 10
If You wan't to verify
Inject this function in MyFirstClass
public void printHashcode(){
System.out.println(st);
}
and then print the hash codes from both methods in MySecondClass
class MySecondClass {
public static void main(String...strings ){
MyFirstClass my =new MyFirstClass();
System.out.println(my.getSt());
my.printHashcode();
}
}
You will see that indeed you are using the Object created in MyFirstClass in MySecondClass.
Because this will give you same hashcode output.
Output On my machine.
Something#2677622b
Something#2677622b
Instead of using the Singleton pattern, a better pattern to use is dependency injection. Essentially, you instantiate the class you want to share, and pass it in the constructor of every class that needs it.
public class MainClass {
public static void main(String[] args) {
SharedClass sharedClass = new SharedClass();
ClassA classA = new ClassA(sharedClass);
ClassB classB = new ClassB(sharedClass);
}
}
public class ClassA {
private SharedClass sharedClass;
public ClassA(SharedClass sharedClass) {
this.sharedClass = sharedClass;
}
}
public class ClassB {
private SharedClass sharedClass;
public ClassB(SharedClass sharedClass) {
this.sharedClass = sharedClass;
}
}
Singleton pattern lets you have single instance which is 'globally' accessible by other classes. This pattern will 'guarantee' that you have only one instance in memory. There are exceptions to one instance benefit, such as when deserializaing from file unless care is taken and readResolve is implemented.
Note that class Something right now has no state(fields), only behavior so it is safe to share between multiple threads. If Something had state, you would need to provide some kind of synchronization mechanism in multi thread environment.
Given such stateless Singleton, it would be better to replace it with class that contains only static methods. That is, unless you are implementing pattern such as Strategy which requires interface implementation, then it would be good idea to cache instance like bellow with Singleton pattern.
You should rework your Something class like this to achieve singleton:
public class Something {
private static final Something INSTANCE = new Something ();
private Something () {
// exists to defeat instantiation
}
public Something getInstance() {
return INSTANCE;
}
public void service() {
//...
}
public void anotherService() {
//..
}
}
If FirstClass and SecondClass are somehow related, you can extract that common object you're using to a super class, and that's the only scope in which you're planning to use this object.
public class SuperClass{
Something st = new Something();
public Something getObjectFromClass(){
return st;
}
}
public class MyFirstClass extends SuperClass{
getObjectFromClass();
}
public class MySecondClass extends SuperClass{
getObjectFromClass();
}
Otherwise, if you plan to use that instance somewhere else you should use a
Singleton object. The easiest way of doing this is:
enum Singleton
{
INSTANCE;
private final Something obj;
Singleton()
{
obj = new Something();
}
public Something getObject()
{
return obj;
}
}
You use it:
Singleton.INSTANCE.getObject();
Okay firstly you can use inheritance e.g.
class MyFirstClass
{
Something st = new Something();
}
class Something()
{
// some code
}
class MySecondClass extends myFirstClass
{
// This is where I want to use the object from class Something()
// like
MySecondClass obj = new MySecondClass();
obj.method(); //Method from myfirstclass accessible from second class object
}
Or if you dont want any objects and just the method you can implement interfaces e.g.
public interface MyFirstClass
{
//example method
public abstract void saying(); //no body required
Something st = new Something();
}
class Something()
{
// some code
}
class MySecondClass implements MyFirstClass //Have to implement methods
{
public void saying(){ //Method implemented from firstClass no obj
System.out.println("Hello World");
}
getObjectFromClass()
}
I'm going to try my best to explain my problem using a scenario:
I have ClassA which contains only one non-static instance of ClassB, many non-static methods that affect that instance of ClassB that we can call EFFECTS and one last non-static getter method that returns that instance of ClassB.
I have ClassC which contains a non-static array of instances of ClassB. In ClassC I have two non-static methods, one that gets a single instance of ClassB from the array and another that sets a single instance of ClassB by the given index value.
What I'm trying to do: I want to have a ClassD that you can create instances of and which acts like an List of EFFECTS, and ClassD would have a non-static method that takes in ClassC as a parameter. That method then applies all these EFFECTS stored in the instance of ClassD to every instance of ClassB stored in the Array of the ClassC parameter provided in this method. Finally this method returns the ClassC with changed ClassB values in its array.
My current solution but I don't know how to get it to work is create an Enum with method references as constants? And then be able to store these in ClassD? And somehow call them? But I'm not extremely familiar with enums, and I've searched online for this but can't find out how to make this work.
Example of Scenario:
public class ClassA {
ClassB classB;
public ClassB get() { return classB; }
public void effectA() {
//affects classB instance
}
public void effectB() {
//affects classB instance
}
public void effectC() {
//affects classB instance
}
}
public class ClassB {
//Code for ClassB
}
public class ClassC {
ClassB[] classBs;
public ClassC(int size) {
classBs = new ClassB[size];
}
public ClassB getB(int index) {
return classBs[index];
}
public void setB(int index, ClassB classB) {
classBs[index] = classB;
}
public int getSize() {
return classBs.length;
}
}
public class ClassD {
ArrayList<Effects> effects;
public ClassD() {
effects = new ArrayList<Effects>();
}
public void addEffect(Effects effect, int effectIntensity) {
//???
}
public void removeEffect(int index) {
effects.remove(index);
}
public ClassC applyEffects(ClassC classC) {
for (int i = 0; i < classC.getSize(); i++) {
ClassB classB = classC.getB(i);
//Apply all effects from effects ArrayList to classB
classC.setB(i, classB);
}
return classC;
}
}
public enum Effects {
//??? Code related to effect methods from ClassA
}
Where the question marks are that's where I don't know how to do this to achieve what I'm trying to do.
I'm going to shorten your example because you have a lot of things going on that I don't think really apply to the question you've asked.
enum constants are basically just public static final instances of the enum class. Therefore you are able to declare abstract methods and override them on each constant.
enum ClassAEffect {
A { #Override void apply(ClassA theA) { theA.effectA(); } },
B { #Override void apply(ClassA theA) { theA.effectB(); } },
C {
#Override
void apply(ClassA theA) {
theA.effectC();
}
};
abstract void apply(ClassA theA);
}
class ClassD {
List<ClassAEffect> effects = new ArrayList<>();
void add(ClassAEffect effect) { effects.add(effect); }
void apply(List<ClassA> list) {
for(ClassA theA : list)
for(ClassAEffect effect : effects)
effect.apply(theA);
}
}
ClassD theD = new ClassD();
theD.add(ClassAEffect.B);
theD.apply(Arrays.asList(new ClassA()));
enum may or may not be appropriate. For example if your design demanded effects for multiple classes, it may be much better to use regular interfaces.
interface Effect<T> {
void apply(T theT);
}
Effect<ClassA> classAEffectA = new Effect<>() {
#Override
public void apply(ClassA theA) {
theA.effectA();
}
};
As another answer notes, this is basically like command pattern and Wikipedia contains a Java example strikingly similar to your own.
Also, in Java 8, you may use method references directly.
class ClassD implements Consumer<List<ClassA>> {
List<Consumer<ClassA>> effects = new ArrayList<>();
void add(Consumer<ClassA> effect) { effects.add(effect); }
#Override
public void accept(List<ClassA> theList) {
for(ClassA theA : theList)
for(Consumer<ClassA> effect : effects)
effect.accept(theA);
}
}
ClassD theD = new ClassD();
// ClassA::effectB implicitly creates a Consumer<ClassA>
// that calls effectB on the ClassA that is passed to it
theD.add(ClassA::effectB);
theD.accept(Arrays.asList(new ClassA()));
Maybe you could use a variant of the command pattern for this?
Class D would be the Invoker and save all the effects (commands) that you want to execute in an array/list. If you don't want to add effects during runtime you could add them in the constructor.
ClassD would have a method executeAllOn(ClassC) that executes all the effects on the objects of ClassB in the ClassC array.
Reference: Command Pattern [wikipedia]
Edit after I saw your example, would look something like this:
public class ClassD {
ArrayList<Effect> effects;
HashMap<Effect, Integer> intensity;
public ClassD() {
effects = new ArrayList<Effects>();
}
public void addEffect(Effects effect, int effectIntensity) {
effects.add(effect)
intensity.put(effect, effectIntensity)
}
public void removeEffect(int index) {
effects.remove(index);
intensity.remove(effects.get(index))
}
public ClassC applyEffects(ClassC classC) {
for (int i = 0; i < classC.getSize(); i++) {
ClassB classB = classC.getB(i);
for (Effect effect : effects) {
effect.execute(classB, intensity.get(effect))
}
classC.setB(i, classB);
}
return classC;
}
}
I know about way how to find which class is calling my method, but this is not sufficient to my.
I have a problem that I have about 200 instances of same class(base class) and they have unique identifier which I can use for analysing problem.
Is there some way, how to find which instances called some method?
I know that debugger allow it, can I do it some how from a code?
You'd pass a reference for that instance to the method being called. For example, say you have two objects:
class ObjectA {
public void methodA() {
new ObjectB().methodB();
}
}
class ObjectB {
public void methodB() {
// How can I know who called me?
}
}
If MethodB needs to know which instance of ObjectA called it, then it would accept that information as a parameter:
class ObjectA {
public void methodA() {
new ObjectB().methodB(this);
}
}
class ObjectB {
public void methodB(ObjectA caller) {
// "caller" is who called me
}
}
There are lots of ways to tweak this. For example, maybe any given instance of ObjectB should have a reference to the ObjectA which created it:
class ObjectA {
public void methodA() {
new ObjectB(this).methodB();
}
}
class ObjectB {
private final ObjectA caller;
public ObjectB(ObjectA caller) {
this.caller = caller;
}
public void methodB() {
// "caller" called me
}
}
Or perhaps you don't want to couple the two objects together and want a more generic approach. You claim that the objects have some kind of identifier, what is that identifier? A String perhaps?
class ObjectA {
private String identifier;
// other code
public void methodA() {
new ObjectB().methodB(identifier);
}
}
class ObjectB {
public void methodB(String callerID) {
// "callerID" identifies who called me
}
}
I have a parent class like
class A{
//Constructors only called by builder.
public static class builder{
//builder code.
}
}
Class B Extends ClassA{
//constrctor
}
Now if i do in my test
final classA dempClassA = new ClassB("parameters here");
how can i call the builder now..?
Sorry guys the builder is a class...My mistake.
If I understand well what you're trying to say, you have the following situation:
public class ClassA {
// Constructors only called by builder.
public static class Builder {
// builder code.
public static void hello() {
System.out.println("Hello");
}
public void hello1() {
System.out.println("Hello1");
}
}
}
And you access it this way:
class ClassB extends ClassA {
public static void main(String[] args) {
ClassA.Builder.hello();
ClassA.Builder builder = new Builder();
builder.hello1();
}
}
If you want to call that method from outside the A class then it shouldn't be private.
If you just want it to be part of the B creation process then you should do something like this:
class B extends A {
public B() {
super(); // invokes A's constructor
}
}
class A {
public A(){
// use builder() here
}
}
Make ClassA's builder method protected (rather than private), so they're visible to ClassB, then use an anonymous class to call it, like this:
ClassA tempClassA = new ClassB("parameters here") {
{
// This block is called during construction
builder();
}
};
Since the builder (is that a class btw? or is the return type missing?) is static, you'd call it like A.builder(). And for it to be visible, you shouldn't make it private :)
Edit: since it is a class, you have several possibilities:
if you need a new instance call new A.builder(...)
if builder provides static methods (in which case the question would be why this is a class) call A.builder.someStaticMethod(...)