how to initialize a private static member of a class in java.
trying the following:
public class A {
private static B b = null;
public A() {
if (b == null)
b = new B();
}
void f1() {
b.func();
}
}
but on creating a second object of the class A and then calling f1(), i get a null pointer exception.
The preferred ways to initialize static members are either (as mentioned before)
private static final B a = new B(); // consider making it final too
or for more complex initialization code you could use a static initializer block:
private static final B a;
static {
a = new B();
}
Your code should work. Are you sure you are posting your exact code?
You could also initialize it more directly :
public class A {
private static B b = new B();
A() {
}
void f1() {
b.func();
}
}
Related
Suppose there are three classes namely A, B and C such that B extends A, C extends B.
Requirement is that client code should be able to call the constructors of each class only once successfully. Upon trying to call constructor twice it should throw an exception.
How can I implement this in Java if duplication of code is not permitted in the child classes?
Example :
public class A {
private static A instance;
public A() {
if (instance != null) {
throw new IllegalArgumentException();
}
instance = this;
}
}
public class B extends A {
private static B instance;
public B() {
if (instance != null) {
throw new IllegalArgumentException();
}
instance = this;
}
}
public class C extends B {
private static C instance;
public C() {
if (instance != null) {
throw new IllegalArgumentException();
}
instance = this;
}
}
public class Driver {
public static void main(String[] args) {
A a1 = new A();
B b1 = new B(); //throwing IllegalArgumentException, it should not throw
}
}
Things I tried.
Maintaining a private static reference of the respective class type which is initially set as null.
In the constructor block I added a null check to assign this reference to the static reference. Did not work as I could not avoid duplicating code.
Requirement
//this should work fine
A a1 = new A();
B b1 = new B();
C c1 = new C();
---------------
//this should throw runtime exception
A a1 = new A();
A a2 = new A();
B b1 = new B();
---------------
//this should throw runtime exception
A a1 = new A();
B b1 = new B();
B b2 = new B();
---------------
//this should throw runtime exception
A a1 = new A();
B b1 = new B();
C c1 = new C();
C c2 = new C();
I hope I am clear with the requirements
Problem
We have established that the subclass implicitly calls the super constructor, which in return throws.
1. Singleton / Factory Method solution
What you want to achieve is described as a Singleton design pattern. It conceptually requires a static members.
Static fields and/or methods (if you want to use a factory method) are not inherited, so duplication of the code which manipulates the static field is inevitable.
You should use the duplicated null-check & store static instance technique, it is widely used and accepted. The amount of code duplication is minimal and you should not be scared of it.
EDITED as to implicit super constructor call: You can use a condition (as in A) or a factory method (as in B).
public class A {
private static A instance;
public A() {
if (this.getClass() == A.class) {
if (instance != null) {
throw new IllegalArgumentException();
}
instance = this;
}
}
}
public class B extends A {
private static B instance;
private B() { }
public static B getInstance() {
if (instance != null) {
throw new IllegalArgumentException();
}
return instance = new B();
}
}
public class C extends B {
private static C instance;
public C() {
// check if (this.getClass() == B.class) when someone extends C
if (instance != null) {
throw new IllegalArgumentException();
}
instance = this;
}
}
public static void main(String[] args) {
A a1 = new A();
B b1 = B.getInstance();
C c1 = new C();
}
Alternatively, you can declare a private constructor and have a static Factory Method. If you are in a multi-threaded environment, pay attention to synchronisation.
2. Collecting all instances in the top-most parent
An other obscure solution would be to collect all Class<> instances in the top parent and check for duplicity in the constructor. This is not a good conventional solution. The singelton pattern is usual.
public class TopClass {
private static final Set<Class<? extends TopClass>> instances = new HashSet<>();
public TopClass() {
if (instances.contains(this.getClass())) {
throw new IllegalArgumentException();
}
instances.add(this.getClass());
}
}
public class SubClass extends TopClass {}
public class AnotherClass extends SubClass {}
This way you limit all future subclasses to be instantiated only once. It is limiting, but yes - less lines of code.
I suppose you can make a Set of already initialized classes and check it every time you construct a new one. It allows create one instance of A, one instance of B and one instance of C.
class A {
private static final Set<Class<? extends A>> calledInitializations = new HashSet<>();
A() {
checkForSecondInit(A.class);
}
protected void checkForSecondInit(Class<? extends A> clazz) {
if (isNotInSuperClassOf(clazz)) {
if (calledInitializations.contains(clazz)) {
throw new RuntimeException("Second init in " + clazz.getName());
} else {
calledInitializations.add(clazz);
}
}
}
private boolean isNotInSuperClassOf(Class<? extends A> clazz) {
return getClass() == clazz;
}
}
class B extends A {
B() {
checkForSecondInit(B.class);
}
}
class C extends B {
C() {
checkForSecondInit(C.class);
}
}
We can create static Set collection and add the classname along with package to set. For new object, it will check if there is a existing class name in the set or not.
For thread safety,set is added in synchronized block.
import java.util.HashSet;
import java.util.Set;
public class A {
static Set<String> set;
public A(){
if(set==null){
synchronized(set){
set = new HashSet<>();
}
}
String classWithPackage = getClass().toString().split(" ")[1];
if(set.contains(classWithPackage)){
throw new RuntimeException("Only one instance can be created for: "+classWithPackage);
}else {
synchronized(set){
set.add(classWithPackage);
}
}
}
}
class B extends A{
public B(){
super();
}
public static void main(String[] args) {
A a = new A();
A a2 = new B();
B b1 = new B();
}
}
The relevant summary of my code is this:
public class A {
String aString;
public static void main(String[] args) {
B b = new B();
new Thread(b).start();
}
public static class B implements Runnable {
public void run() {
aString = "foo";
}
}
}
I have had a few months of Java coding experience but thread and dynamic vs. static is still rather new to me. In order for the thread to execute properly, class B must be static, or else only the thread executes, not both. My goal is to obviously have the thread execute in the background so that other code that I may have in class A can execute simultaneously. Problem is, if class B is static, I can't manipulate the string aString, as I get the exception non-static variable aString cannot be referenced from a static context.
I've looked up information on this but I have not found anything that relates to fixing this issue in threads. My question is, how can I manipulate aString within class B and still get the thread to work properly (both classes running, not just class B)?
To make your example work, you'll need something like this:
public class A {
volatile String aString;
public static void main(String[] args) throws InterruptedException {
A a = new A();
Thread t = new Thread(a.new B());
t.start();
t.join(); // wait for t to finish
System.out.println(a.aString); // prints "foo"
}
class B implements Runnable {
public void run() {
aString = "foo";
}
}
}
Resolving the static issue is the easy part - see code for how.
I hope the rest of the code helps illustrate some of the issues you need to cater for when using threads.
B is static, so only only exists at the class level, and can therefore not see instance variables of its parent class
public class A {
String aString; // <== instance variable
public static void main(String[] args) {
B b = new B();
new Thread(b).start();
}
public static class B implements Runnable { // <== static class
public void run() {
aString = "foo";
}
}
}
Possible fix. Make aString static too
public class A {
static String aString;
Possible fix. Make B non-static. This is where it gets a bit weird. B now only exists at the instance level of A, so you need to create an A instance first.
public class A {
String aString;
public static void main(String[] args) {
B b = new A().new B(); // <== need to create an A before a B
new Thread(b).start();
}
public class B implements Runnable {
public void run() {
aString = "foo";
}
}
}
You are asking an object instance of class B (which you create using new B() )to access a member variable of an object instance that you haven't created. In your code, there is no object of class B created.
I think that you may be thinking that running the main() method in class A is somehow instantiating an instance of class A - this is not the case.
The following will work because you are creating an instance of A and making that available to your instance of B.
public class A {
String aString;
public static void main(String[] args) {
A a = new A();
B b = new B(a);
new Thread(b).start();
}
public static class B implements Runnable {
private final A a;
public B(A a){
this.a = a;
}
public void run() {
a.aString = "foo";
}
}
}
Why isn't this code working
public class BB
{
private class A
{
private int x;
}
public static void main(String[] args)
{
A a = new A();
a.x = 100;
System.out.println(a.x);
}
}
while this code is working?
public class BB
{
private class A
{
private int x;
}
static int y = 3;
public static void main(String[] args)
{
BB b = new BB();
b.compile();
System.out.println("y = "+ y);
}
public void compile()
{
A a = new A();
a.x = 100;
System.out.println(a.x);
System.out.println("y = "+ y);
}
}
In first code, When I am trying to refer to instance variable 'x' of inner class 'A' by an object of inner class 'a', I am getting an error saying that I'm using inner class in static context.
There is no error while doing the same in some other method.
Your error has nothing to do with field access. Compilation fails for this line:
A a = new A();
Reason: you cannot instantiate an inner class without an enclosing instance, which is exactly what that line of code tries to do. You could write instead
A a = (new BB()).new A();
which would provide an enclosing instance inline. Then you will be able to access the private field as well.
Alternatively, just make the A class static, which means it does not have an enclosing instance.
private class A is like an instance member and we can not use instance member inside static method without making its object. So first we need to object of outer class than we can use instance inner class. And below code is working fine.
class BB
{
private class A
{
private int x;
}
public static void main(String[] args)
{
BB bb = new BB();
BB.A a = bb.new A();
a.x = 100;
System.out.println(a.x);
}
}
here is my problem
class A{
private B b = new B(this); // line 2
A(){}
}
This is just an ex. code and works fine. But i have a doubt about this is used to current reference (instance of A). Class initializing happens before to get a class instance. So how can we put this in line 2. i asked does instantiation happen before initializing?
You bring up an interesting point. Here is a contrived instructional example that demonstrates a run time problem that can happen when using your example.
class A {
private boolean isInitialized = false;
private final B b = new B(this);
public A() {
initialize();
}
private void initialize() {
isInitialized = true;
}
public boolean isInitialize() {
return isInitialized;
}
public B getB() {
return b;
}
}
class B {
private boolean isInitialized = false;
final private A a;
public B(final A a) {
this.a = a;
initialize();
System.out.println("inB: a.isInitialize()=" + a.isInitialize());
}
private void initialize() {
isInitialized = true;
}
public boolean isInitialize() {
return isInitialized;
}
}
public static void main(final String[] args) {
final A a = new A();
System.out.println("inMain: a.isInitialize()=" + a.isInitialize());
System.out.println("inMain:a.getB().isInitialize()=" + a.getB().isInitialize());
}
Output:
inB: a.isInitialize()=false
inMain: a.isInitialize()=true
inMain:a.getB().isInitialize()=true
Using the passed reference to class A within class B runs the real risk of using an object that is not fully initialized.
Be careful.
This is not class initialization (try to debug new ClassA() step by step), it is actually instance initialization.
There can be some problems if the constructor (from ClassB) calls some functions from ClassA, which access some fields in ClassA that are not initialized.
Edit: this is done before the constructor is called.
this is used correctly. The constructor doesn't need to be called at all.
No need for changes, everything is fine. this is a valid reference to A.
this will show its existence when you create an object of class A. Instance variable are assigned after object creation and static variable are initialize as soon as class loads and also before creations of any object.
you cannot use above initialization in static block
static {
private B b = new B(this); // compiler error. you cannot use 'this' in static context.
}
Presume we have two different packages... one package can't be accessed but we like to know the value of a complex field called b.
public class A {
private String whatever;
private B b;
private static class B {
final ArrayList<Z> c = new ArrayList<Z>();
private void addItem(Z z) {
this.c.add(z);
}
private Z getItem(int nr) {
return this.c.get(nr);
}
}
}
public class Reflect extends A {
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
Reflect ref = new Reflect();
Class getA = ref.getClass().getSuperclass();
Field getB = getDeclaredField("b");
getB.setAccessible(true);
Class bInst = getB.getClass();
Method bMeth = bInst.getMethod("getItem", Integer.TYPE);
Object zInst = bMeth.invoke(new Integer(123));
}
}
How can I get the value if I don't get the complex type B from the package ?
Still get java.lang.NoSuchMethodException: stackOver.A.getItem(int) even I set the field gstB accessible ....
The only thing you are missing is that getField only gives you public accessible fields.
Field getB = getA.getDeclaredField("b");
will give you any field of that class.
A longer example
class Main {
public static class A {
private String whatever;
private B b = new B();
private static class B {
final ArrayList<String> c = new ArrayList<String>();
private void addItem(String z) {
this.c.add(z);
}
private String getItem(int nr) {
return this.c.get(nr);
}
}
}
public static class Reflect extends A {
public static void main(String... ignored) throws Exception {
Reflect ref = new Reflect();
Class getA = ref.getClass().getSuperclass();
Field getB = getA.getDeclaredField("b");
getB.setAccessible(true);
Object b = getB.get(ref);
Method addItem = b.getClass().getDeclaredMethod("addItem", String.class);
addItem.setAccessible(true);
addItem.invoke(b, "Hello");
Method getItem = b.getClass().getDeclaredMethod("getItem", int.class);
getItem.setAccessible(true);
String hi = (String) getItem.invoke(b, 0);
System.out.println(hi);
}
}
}
prints
Hello
How can I get the value if I don't get the complex type B from the package ?
You can get it as an Object, and then use reflection to further discover the methods that it exposes.
Object bInst = ... // Get b through reflection
Class bClass = bInst.getClass();
Method[] bMeth = bClass.getMethod("getItem", Integer.TYPE);
Object zInst = bMeth.invoke(new Integer(123));
Use commons beanutils library and use following method, it is much cleaner than doing it yourself
PropertyUtils.getNestedProperty(ref, "b.propertyOfClassB");
replace propertyOfClassB with actual property name.