This question is a common issue, and I have tried to look at some thread as Is Java "pass-by-reference" or "pass-by-value"? or How to change an attribute of a public variable from outside the class
but in my case I need to modify a boolean variable, with a Singleton instance.
So far I have a class, and a method which changes the boolean paramter of the class. But I would like to separate this mehod in a manager. The scheme is something like:
public class Test{
private boolean b;
public String getb(){}
public void setb(){}
String test = ClassSingleton.getInstance().doSomething();
}
public class ClassSingleton{
public String doSomething(){
//here I need to change the value of 'b'
//but it can be called from anyclass so I cant use the set method.
}
}
Thanks,
David.
If I understand your requirement - this can solve your problem:
public interface IUpdatable
{
public void setB(boolean newValue);
}
public class Test implements IUpdatable
{
private boolean b;
public String getb(){}
public void setB(boolean newValue) {this.b = newValue;}
}
public class ClassSingleton
{
public String doSomething(IUpdatable updatable)
{
updatable.setB(true);
...
}
}
This way the Singleton does not need to know your Test class - it just knows the interface IUpdatable that supports setting the value of B. Each class that needs to set its B field can implement the interface and the Singleton can update it and remain oblivious to its implementation.
You could extract public void setb(){} into an interface (let's call it BSettable), make Test implement BSettable, and pass an argument of type BSettable into doSomething.
Alternatively, you could make b into an AtomicBoolean and make doSomething accept (a reference to) an AtomicBoolean.
Define b as static variable.
Then call Test.b = value
Perhaps:
public class Test {
private static boolean b;
public static String getB() {}
public static void setB() {}
}
should help? Static fields and methods can be called without an instance (i.e. Test.setB();).
I think your question is not very clear and your sample code is really badly done. Do you actually mean something like this?
public class Test{
private boolean b;
public boolean getb(){return b;}
public void setb(boolean b){this.b = b;}
String test = ClassSingleton.getInstance().doSomething(this);
}
public class ClassSingleton{
private static ClassSingleton __t__ = new ClassSingleton();
private ClassSingleton() {}
public String doSomething(Test t){
t.setb(true);
return null;
}
public static ClassSingleton getInstance(){
return __t__;
}
}
Do you mean your manager is a singleton? or your test class should be singleton? Please be more specific
Related
I'm trying to understand how the static method calls from a Java enum works.
To see the full code of this "Working example"
I have the following scenario working, I don't know why
public enum Condition {
GREATER_THAN(PredicateBuilder::generateGreaterThan, ">"),
more values...
private Condition(BiFunction<PredicateBuilder, PredicateContent<?>, Predicate> predicate, String operator) {
this.operator = operator;
this.predicate = predicate;
}
This is the predicate builder, it's an interface implemented by a #Component from Spring:
#Component
public class PredicateLogicalBuilder<V extends Comparable> implements PredicateBuilder<V> {
#Override
public Predicate generateGreaterThan(PredicateContent<V> predicateContent) {
return predicateConversion(predicateContent,Condition.GREATER_THAN);
}
}
The static reference in above Condition enum doesn't complain about:
Non-static method cannot be referenced from a static context
and I don't why because now I'm trying to do something similar and it fails because the static reference of a method isn't static. In the code above is not static either.
Code I'm trying:
public interface MethodCalls<T> {
void randomMethod(T content);
}
#Component
public class TestEnumMethoCalls implements MethodCalls<SomeBean> {
#Override
public void randomMethod(SomeBean content){
System.out.println("Works!!!!");
}
}
public enum NotificationType {
ENUM_TEST_1(MethodCalls::randomMethod);
public final Function<SomeBean,Void> method;
private NotificationType(Function<SomeBean,Void> method){
this.method=method;
}
}
public class TestClass{
public void testMethtod(){
NotificationType.ENUM_TEST_1.method.apply(new SomeBean())
}
}
This piece of code fails saying the Non-static method cannot be referenced from a static context:
ENUM_TEST_1(MethodCalls::randomMethod);
I would like to have 2 answers:
Why the code of the "Working example" works.
If it's mandatory for my current test to use the instance of the MethodCalls how can be injected with DI to the enum (is a static context so I understand it might be tricky if not impossible).
Thanks for the help, now I understood why my "working example" works and how to "Fix" my current issue:
To fix it I have to pass an instance of the implementation of the interface as it's pointed out that enums can only access static methods or an instance of the object to access the method that way.
Final Code
public enum NotificationType {
ENUM_TEST_1(MethodCalls::randomMethod);
public final BiFunction<MethodCalls,SomeBean,Void> method;
private NotificationType(BiFunction<MethodCalls,SomeBean,Void> method){
this.method=method;
}
}
So when I call the apply it looks like this:
public class TestClass{
#Autowired MethodCalls methodCalls;
public void testMethtod(){
NotificationType.ENUM_TEST_1.method.apply(methodCalls,new SomeBean())
}
}
I someone finds out a cleaner way to do this, I would apreciate it.
This question already has answers here:
Is there a way to override class variables in Java?
(17 answers)
Closed 6 years ago.
In Java, I have had several projects recently where I used a design pattern like this:
public abstract class A {
public abstract int getProperty();
}
public class B extends A {
private static final int PROPERTY = 5;
#Override
public int getProperty() {
return PROPERTY;
}
}
Then I can call the abstract method getProperty() on any member of class A. However, this seems unwieldy - it seems like there should be some way to simply override the property itself to avoid duplicating the getProperty() method in every single class which extends A.
Something like this:
public abstract class A {
public static abstract int PROPERTY;
}
public class B extends A {
#Override
public static int PROPERTY = 5;
}
Is something like this possible? If so, how? Otherwise, why not?
You cannot "override" fields, because only methods can have overrides (and they are not allowed to be static or private for that).
You can achieve the effect that you want by making the method non-abstract, and providing a protected field for subclasses to set, like this:
public abstract class A {
protected int propValue = 5;
public int getProperty() {
return propValue;
}
}
public class B extends A {
public B() {
propValue = 13;
}
}
This trick lets A's subclasses "push" a new value into the context of their superclass, getting the effect similar to "overriding" without an actual override.
What I'm trying to do is instantiate an object in the parent class called "pObject" (assume the type to be protected Boolean). One child class which extends the parent class sets "object" to "true". The other child class which also extends the parent class will check to see if "object" is set to true.
Is this possible in Java?
public abstract class parentClassAction{
protected Boolean pObject;
}
public class childClass1Action extends parentClassAction{
super.pObject = true;
}
public class childClass2Action extends parentClassAction{
if(super.pObject!=null){
if(super.pObject == true){
System.out.println("Success");
}
}
}
You can make pObject static and access it as parentClassAction.pObject.
If you have 2 different instances of subclasses - they do not share any state. Each of them has independent instance of pObject, so if you change one object it will not be seen in another one.
There are many ways to solve your problem. The easiest way: you can make this field pObject to be static - it will work for simple example, but this can be also serious limitation (if you want to have more than one instance of pObject).
Yes. If pObject is static it will be shared:
public class Legit {
public static abstract class A {
protected static Boolean flag;
}
public static class B extends A {
public void setFlag(boolean flag) {
super.flag = flag;
}
}
public static class C extends A {
public boolean getFlag() {
return super.flag;
}
}
public static void main (String [] args) {
B b = new B();
C c = new C();
b.setFlag(true);
System.out.println(c.getFlag());
b.setFlag(false);
System.out.println(c.getFlag());
}
}
You can access non private fields of a super class using the syntax:
super.myBoolean = true;
Note: If the field has the default visibility (absence of modifier) it is accessible only if the sub class is in the same package.
Edited: I add information due to the new code added to the question.
It seems that you like to check a variable from two different objects. It is possible only if that variable is static. So declare it as protected static in the parent class. The rest of code rest the same.
So I have this abstract class
public abstract class A {
protected final boolean b;
protected A (boolean b){
this.b = b;
}
}
And this class that extends A
public class C extends A{
protected C() {
super(false);
}
}
I dont want "b" to be able to change its' value once it's initialized
But I dont know how to do it without the compiler going haywire.
Any suggestions are welcome. Thanks in advance.
EDIT1: static removed from b.
EDIT 2: Ok realised the problem and fixed see above.
Special thanks to J.Lucky :)
I'd suggest you make use of the final keyword.
Try the following codes:
abstract class A {
final protected boolean b;
A(boolean b) {
this.b = b;
}
//No setter method
//public abstract void setB(boolean b);
public abstract boolean getB();
}
class C extends A {
C(boolean b) {
super(b);
}
#Override
public boolean getB() {
return b;
}
}
Sample implementation would be:
public static void main(String args[]) {
C c = new C(true);
System.out.println(c.getB());
}
Since b now is a final variable, you will be forced to initialize it on your constructor and you will not have any way of changing b anymore. Even if you provide a setter method for b, the compiler will stop you.
EDIT 2:
Say you created another class called 'D' and this time you know you want to set it to false by default. You can have something like:
class D extends A {
D() {
super(false);
}
//You can also overload it so that you will have a choice
D(boolean b) {
super(b);
}
#Override
public boolean getB() {
return b;
}
public static void main(String[] args) {
D defaultBVal = D();
D customBVal = D(true);
System.out.println(defaultBVal.getB()); //false
System.out.println(customBVal.getB()); //true
}
}
Solution: You should change the boolean into a Boolean, make it private, provide a getter and a protected setter. In the setter you should check whether the Boolean has been initialized. If so, you should either ignore resetting, or throw and Exception
well how about this:
public abstract class A {
private static Boolean b;
//setB is declared here and, depending on the class that implements it,
//it initializes the value of the variable "b"
protected abstract void setB();
}
public class C extends A{
protected void setB() {
if(b != null) b = true;
}
}
Now the variable is only initialized once when its called. There are still some problems. Someone could use reflection to change the value. Also, when the object is serialized is possible that someone could change the value. If you have a multiple threads accessing this then you should synchronize the method. However, if these aren't issues then this solution might work for you.
Is there anyway, when calling a method through an object (instance) for that method to know which instance (object) called it?
Here's an example (pseudo code) of what I mean:
Pseudo code example
public class CustomClass{
public void myMethod(){
if (calling method is object1){
//Do something here
}
else {
//Do something else
}
}//End of method
}//End of class
And then in another class:
public SomeOtherClass{
CustomClass = object1;
public void someOtherMethod(){
object1 = new CustomClass();
object1.myMethod(); //This will call the 1st condition as the calling object is object1, if it were some other object name, it would call the 2nd condition.
}//End of method
}//End of class
Possible work-around
The only way I've found to do this is to get the method to take another argument, say an 'int' and then check the value of that int and perform whichever part of the 'if else' statement relates to it (or 'switch' statement if definitely using an 'int' value) but that just seems a really messy way of doing it.
What you need is the Strategy Pattern
public abstract class CustomClass {
public abstract void MyMethod();
}
public class Impl1 extends CustomClass {
#Override
public void MyMethod() {
// Do something
}
}
public class Impl2 extends CustomClass {
#Override
public void MyMethod() {
// Do something else
}
}
Use it this way
public static void main(String[] args) {
CustomClass myObject = new Impl1();
// or CustomClass myObject = new Impl2();
}
As your comment says what you really need is perhaps the Template method Pattern
public abstract class CustomClass {
public void myMethod(){ // this is the template method
// The common things
theDifferentThings();
}
public abstract void theDifferentThings();
}
public class Impl1 extends CustomClass {
#Override
public void theDifferentThings() {
// Do something
}
}
public class Impl2 extends CustomClass {
#Override
public void theDifferentThings() {
// Do something else
}
}
You can know the name of current class by calling getClass().getName(). However you cannot know the name of object, moreover this does not have any meaning:
MyClass myObject1 = new MyClass();
MyClass myObject2 = myObject1;
myObject1.foo();
myObject2.foo();
Do you wutant foo() to know that it was invoked using myObject1 or myObject1? But both references refer to the same object!
OK, there are extremely complicated ways to know this. You can use byte code engineering using one of popular libraries like javassist, ASM, CGLib and inject missing information about the "object name" into byte code and then read this information. But IMHO this is not what you need.
You can define a new attribute inside CustomClass which will store the identifier of the instance. If there will be only a few instances of CustomClass then you can use an enum type.
Replace:
object1 = new CustomClass();
with:
object1 = new CustomClass(1);
Add a new constructor and an attribute to CustomClass:
private int id;
public CustomClass(int id) {
this.id = id;
}
Then you can replace:
if (calling method is object1){
with:
if (id == 1){
However, please keep in mind that this is a bad design.
You should not have if conditions differing logic depending on the instance which called this method. You should should use polymorphism for such purpose.