Java static methods with class level variables - java

I have static method when multiple threads are accessing , will the data updated incorrectly,
public class A
{
private static B b=null;
public static B create()
{
b= new B();
return b;
}
public static B process()
{
// doing some processing with b;
return b;
}
}
If multiple threads are accessing simultaneously, Will B get affected?

If you want to protect the value and ensure it is updated correctly, then you should make the method synchronized.

No, because b exists on object level and is not statically accessible.

No one can tell until we see the way you access and work on b.
However, one thing I can tell is, static or not is usually not a main factor that affect thread-safetiness.

Related

How many times static methods will be executed in java

This is related to the below thread :
https://stackoverflow.com/questions/18402564/how-do-static-methods-work
Suppose I have a static method in a class (TestClass), which queries the DB and stored it in a static variable, and returns it.
public static List<MyClass> getMyData()
{
setMyDataList(getMyNewData.execute());//DB Call and assigns the result to the static variable.
return myDataList;// returns the static variable
}
In this case, say class A calls TestClass.getMyData() which fetches the data and stores in the myDataList, and then class B calls TestClass.getMyData(), will the DB be hit again ?
Static block is not equals to static method.
In case of static block:
That static block loads when class loader loads that class. Unless you have multiple class loaders, only once it executes and that data you inserted will be shared across all the instances.
Incase of static method :
It's almost like an instance method and you'll be hit those many times you call that method. Diff is only you don't need an instance to invoke it.
You not at all need that method. Put your code in a static block an hit DB there and insert into list. You can access that list with static and don't forget to make that list static.
yes it will be 'hit' again...
If you don't want that you might want to have a flag in your static class that indicates if the method was already called:
private static boolean methodAlreadyCalled = false;
public static List<MyClass> getMyData()
{
if (!methodAlreadyCalled)
{
setMyDataList(getMyNewData.execute());
methodAlreadyCalled = true;
}
return myDataList;
}

Is lazy initialization with immutable data always thread-safe?

I have two classes A and B:
class A {
private final String someData;
private B b;
public String getSomeData() { return someData; }
public B getB() {
if (b == null) {
b = new B(someData);
}
return b;
}
}
where B is immutable and computes its data only from an instance of A. A has immutable semantics, but it's internals are mutable (like hashCode in java.lang.String).
When I call getB() from two different threads, and the calls overlap, I assume each thread gets its own instance of B. But since the constructor of B gets only immutable data, the two instances of B should be equal.
Is that correct? If not, must I make getB() synchronized to make it thread-safe?
Assume that B implements equals(), which compares all instance variables of B. Same for hashCode()
This is not thread-safe, because you haven't created any "happens-before" relationships with volatile or synchronized, so it's possible for the two threads to interfere with each other.
The problem is that although b = new B(someData) means "allocate enough memory for an instance of B, then create the instance there, then point b to it", the system is allowed to implement it as "allocate enough memory for an instance of B, then point b to it, then create the instance" (since, in a single-threaded app, that's equivalent). So in your code, where two threads can create separate instances but return the same instance, there's a chance that one thread will return the other thread's instance before the instance is fully initialized.
For "But since the constructor of B gets only immutable data, the two instances of B should be equal."
As you understand its not thread safe, one thread might get un-initialized B instance (B as null or inconsistent state where somedata not yet set) others might get b instance with somedata set.
To fix this you need synchronized getB method or use synchronized block with double-check lock or some non-blocking technique like AtomicReference. For you reference I am adding here sample code for how to achieve the correct threadSafe getB() method using AtomicReference.
class A {
private final String someData = "somedata";
private AtomicReference<B> bRef;
public String getSomeData() { return someData; }
public B getB() {
if(bRef.get()== null){
synchronized (this){
if(bRef.get() == null)
bRef.compareAndSet(null,new B(someData));
}
}
return bRef.get();
}
}
class B{
public B(String someData) {
}
}

Are static class members static in Java?

In the below code, are b and show inherently static?
public class A {
public static class B {
private int b = 0;
public void show() {
System.out.println(b);
}
}
}
No they aren't static. You need to create an instance of B to access them.
The static keyword in your code example means that instances of B can be created without an instance of A.
If B was not static:
Instances would have an implicit reference to an instance of A.
The only way to create them would be to use new B() inside class A, or using syntax like new A().new B().
Methods in B can refer to A.this (the implicit reference to an instance of A).
Methods in B can refer to A.this.someField (using that implicit reference).
Methods in B can call instance (non-static) methods in A.
However, because B is static:
Instances do not have a reference to an instance of A - you don't need an A to create a B.
Instances can be created using new A.B() (or just new B() from within in class A)
Methods in B cannot refer to A.this.
Methods in B cannot access fields in A (unless passed in as a parameter).
Methods in B cannot call instance (non-static) methods in A.
They are not static. They are instance fields in B.
Meaning you need to have an instance of B to get/set them.
B is static in A but that does not make those fields of B static.
You can create many instances of B without any reference to A.
So B is static class in A but the same is not true for B's instance fields.
The static keyword has two meanings that are actually quite different and that can be confusing.
Static on a variable/method means that it exists at the class level, not the instance level. This means that you only have one copy of that variable/method no matter how many instances of the class you create.
Static on an inner class though just means that the class does not depend upon its outer class. In your example you can create a new B() without having an A. If you didn't have the static keyword on the class you could not create a new B() unless it was within an instance of A.
B is a static inner class of A.
Need to instantiate B.
A.B innerObject = new A.B();
innerObject.show();
The identifier static has a specific purpose here that many people don't immediately grasp. I'm going to take your code and change it a bit.
public class A {
private int a;
public A(int a) {
this.a = a;
}
public class B {
public void show() {
System.out.println(a);
}
}
}
Now, what's happening in class B? Because B is a non-static class, it has access to other non-static members in class A. Essentially, it states that every class A object has their own flavor of class B objects, even thought they are functionally the same. For us to get that same behavior if B was a static class:
public class A {
private int a;
public A(int a) {
this.a = a;
}
public int getA() { return a; }
public static class B {
public void show(A a) {
System.out.println(a.getA());
}
}
}
Here, this implies that the flavor of B objects doesn't change depending on which A object created it. The B class is static so that it cannot access non-static members of the A class object that created it and must access those members explicitly from whichever A object it wants to interact with.
In the previous implementation, a B object would seamlessly access fields and non-static methods of the A object that created it.
These are two different behaviors and often it's clear exactly which one fits your objective.

Call constructor within constructor with self(this)-parameter

I need to link an object of type B to any instance of type A (circular dependencies). I could also declare another method, which must be called after the constructor of A and link a new B to an A-instance. What I want to achieve is not having to call such a method manually. This is the sample code:
public Class A{
B b;
public A(){
b = new B(this); // this does not work,
// as this references an object that has not been created yet
}
}
public Class B{
A a;
public B(A a){
this.a = a; //or something else
}
}
I commented the problematic line. I also understand why it can't work. What I need to know is, if there is a well-known design pattern to avoid this problematic? Or should I just redesign my class model, putting anything in B to A? Any suggestions?
It does work. It's problematic in that it exposes an object before it's been fully initialized (so if the B constructor calls methods on the parameter, for example, that could be a bad thing), but it does work. The reference B.a will be a reference to the instance of A that's been/being constructed.
I would recommend trying to avoid the cyclic reference where possible, but where the alternative is even worse, the code you've given will work.
Using this approach is not recommended and possibly create runtime exception because the object is not fully initialized. We can take simple scenario as:
public class A {
B b;
String s;
public A(){
b = new B(this); // this does not work, as this references an object that has not been created yet
s = "print me";
}
}
public class B {
A a;
public B(A a){
this.a = a; //or something else
System.out.println(this.a.s); // will same as a.s;
}
}
It will output null because a partially initialized reference is copied to constructor. This code compiles because compiler doesn't find anything missing in code as all appropriate references and variable are there.

basic exercise in java

I have two classes A and B as follows:
public class A {
private int salary = 0;
protected void calculate() {
salary = 400;
}
protected A() {
calculate();
}
}
public class B extends A {
private int salary = 0; // (1)
protected void calculate() {
System.out.println("calculating salary...");
salary = 700;
}
public static void main(String[] args) {
System.out.println(new B().salary); // (2)
}
}
Consider line (2): I don't understand why new B().salary is valid because the specifier of salary in line (1) is private. Could you help me explain it?
You can access B.salary because your code is executing inside the class B.
A common misconception of private (or all access modifiers, in fact) is that it acts on a per-object basis, which is not true. A private field is private to the whole class. So every instances of B can access the salary field of each other B object. Even static code in B can do that.
Also note that you're needlessly complicating matters by introducing the class A: it has no actual effect on your example, you can simply leave it out.
I don't see any private constructor of B so new B() is valid + the private field is accessible within same class
private applies to things outside the class definition, everything inside the class definition can see them.
main is a (static) member of B, so it can see private members.
Every class has access to its private parts.
It is valid since main is inside the B class, which means all fields (even private) are visible to it.
If you move main to another class, it will not be valid anymore.
Private fields can be accessed only from within the same class. So salary can only be accessed from class B.
Since your main method is in class B, you can access it.
salary in line 2 is referring to the salary you declared in class B, and your main method is part of class B so main can see any private stuff of B.
Every class has access to its private members. And "salary" is in class, along with your main method. That's why main method can access "salary".
Line 2 is the same as doing this:
B bObject = new B();
System.out.println(b.salary);
You can access the private variable because "bObject" is of type B. Now what you couldn't do is:
A aObject = new A();
aObject.bSalary;//if you changed the name of the salary variable to bSalary

Categories

Resources