How to call static block of class in java - java

I have class which has static block as follows:
public class DataProvider {
static int a;
static String b;
static {
a = readRollConfiguration();
b = readNameConfiguration();
}
public static int getRoll() {
return a;
}
}
I change configuration and call methods of this class then i get older values of a and b, until app is killed and restart.
So is there any way to call static block so that a and b get updated?

a and b are just loaded once. If you want to call the methods readRollConfiguration and readNameConfiguration every time you call the method getRoll, you have to call that method there.
public class DataProvider {
public static int getRoll() {
return readRollConfiguration();
}
}

You can use Class.forName("com.the.ClassName"); to call static block without ceating any instance of that class.

You are initializing the values of static variables a and b as part of DataProvider class initialization using a static initializer block and these values will be same unless you change the static values again.
So, update your DataProvider class and add reloadRollConfig() and reloadNameConfig() as shown below for reloading the values again from configurations:
public class DataProvider {
static int a;
static String b;
static {
a = readRollConfiguration();
b = readNameConfiguration();
}
public static int getRollConfig() {//no reload, gets the current value
return a;
}
public static int getNameConfig() {//no reload, gets the current value
return b;
}
public static int reloadAndGetRollConfig() {//reload and get the new value
a = readRollConfiguration();
return a;
}
public static int reloadAndGetNameConfig() {//reload and get the new value
b = readNameConfiguration();
return b;
}
}
Yes, I know its bad idea, but configuration changes not very often.
I strongly suggest you reload the values of a and b periodically to set the latest values to the DataProvider class. You can do this by using a simple scheduler or implement a caching layer using frameworks like Ehcache. Caching frameworks provide many features for caching the static data and I suggest you need to consider implementing caching for this kind of configuration data (i.e., the data which does not change very often).

You can't call static block. It is called when Class object is created. You can think of it as constructor of Class object that describes your class. Unlike constructor which is called when instance is created.

The way you have done is completely wrong. static block will run only once whenever your class is loaded.
public class DataProvider {
static int a;
static String b;
static {
a = getSum();
b = "15";
}
public static int getSum(){
return 5 + 6;
}
public static int getRoll() {
return a;
}
}
So in this piece of code variable a will be created and assigned value 11 whenever DataProvider class is loaded. And, the point is that this value will be same until unless DataProvider class will not be recompiled or reloaded. Even, if the getSum() return new value each time, variable a gonna contain first value only.
So if you want a to be dynamic you have update variable every time you want to access a like this:
public static int get_a() {
return a = getSum();
}

Related

Java Inheritance issue with static and non-static context

Please help me I am facing bit problem in Java code.
I am not able to understand how to fix the error.
Please help.
public class A {
private int a = 100;
public void setA(int value) {
a = value;
}
public int getA() {
return a;
}
}
public class B extends A {
private int a = 222;
public static void main(String[] args) {
System.out.println("in main(): ");
a = 123;
System.out.println("a = "+super.a );
}
}
The error I get is:
int a in class Main must be static
First of all, you should tell us the error :).
It looks like you are trying to access a variable in a non-static context from a static context (main method is static).
You should do something like below:
public class B extends A {
public static void main(String[] args) {
B b = new B();
b.setA(123)
System.out.println("a = " + b.getA());
}
}
It doesn't make sense to declare another 'a' variable in the child class. If you want to access 'a' directly, you can declare the field in class A as protected.
First of all, just to be clear prior to going to the code, your 2 classes, given they are both public, must be in their own separate files.
Now let's go to your code. The error lies first in this statements inside your main method:
a = 123;
You are accessing B's instance variable a from a static context -this is one.
Second:
System.out.println("a = "+super.a );
A's instance variable a is never inherited by B because it has a private access modifier.
If you want to access A's a, you could create an instance of A, and use that to call the getA() method which returns the value of A's a
Cheers,

Why is my instance variable accessible without an instance?

My understanding of the Instance variables is that they are created when an object is created. If that is true then why can print the variable "data"? Shouldn't I have to create an object of class JavaTesting first?
public class JavaTesting
{
static int a = 1;
private int data = 99;
#Test
public void f1()
{
System.out.println("Print a = "+a);
System.out.println("Print data = "+data);
}
}
Your method f1() is not a static method. This means it can only be called on an instance. Whatever method is calling f1() is probably creating an instance of JavaTesting first. If you made f1() static, your IDE would probably have a fit and start coughing up red flags.

How to pass value by reference in this case?

I need a way to check if a boolean value of another object is true, and only in that case should do something.
So, I have 2 classes:
public class A{
private boolean test = false;
...
...
public boolean returnTest(){ return test; }
}
public class B{
private boolean abcd;
public B(A myA){
this.abcd = myA.returnTest();
}
public void test(){
while(!abcd){
// wait
}
// do something
}
}
The problem is that it remain in the while loop forever even if the test value of the object A become true. Why ?
In your case, pass instance to function test() is better, invoke test() with passing instance of A. Everytime an new instance of A is created or an existing instance has updated its attributes, pass it to test()
public void test(A a){
while(!a.returnTest()){
// wait
}
}
There is no real alternative to changing test() to do while (!myA.returnTest()). If you store a result in a variable it will stay permanently. (Properties of objects, or method calls, can reflect changes elsewhere, but variables themselves cannot.)
Booleans are immutable so you cannot make a copy of a reference to them.
Instead, try:
public class B{
private A a;
public B(A myA){
this.a= myA();
}
public void test(){
while(!myA.returnTest()){
// wait
}
// do something
}
}
In Java 8 you can use a method reference.
public class A{
private boolean test = false;
...
...
public boolean returnTest(){ return test; }
}
public class B{
private BooleanSupplier abcd;
public B(A myA){
this.abcd = myA::returnTest; // a reference to this method.
}
public void test(){
while(!abcd.getAsBoolean()) { // calls the method each time.
// wait
}
// do something
}
}
If you must do so, one option is to use a java.util.concurrent.atomic.AtomicBoolean, which is mutable type. You can retrieve and update values using get() and set(boolean) respectively. This can also be a good option if thread-safety can potentially be a concern in your application.
Otherwise you have to store a reference to the A instance and use the flag inside it instead of checking a different variable.

How to Transfer values to another class method

I have global variables in Question class and increments these values in event handler. I have another class User which contains a static method Details(). I want to pass these two variables values (after increments) from event handler to the Details() of the User class.:
public class Question {
public int phCounter = 0;
public int chemCounter = 0;
private void CategoryCbActionPerformed(java.awt.event.ActionEvent evt) {
phCounter++;
chemCounter++;
}
}
...
public class User {
static void Details() {
public counter ;
}
}
My question is is there any way, except to send values as arguments to Details(), in which I can inject these incremented values inside Details() method.
First off: Method names in Java are camelCase. Not UpperCase ;)
If you want to access fields of a class in another class there are serveral ways to achieve that. The easiest one are static fields:
public class MyClass {
public static String accessible;
}
public class AnotherClass {
public void someMethod() {
// You can set the value ...
MyClass.accessible = "New value";
}
public void anotherMethod() {
// ... and get the value.
System.out.println(MyClass.accessible);
}
}
But remember: The value of a static field will be always the same unless you change it, even when you create new instances of the class where the static field is used. You should avoid static fields if possible. In most cases you can take the OOP way to achieve the same result.
~ Morph
I can inject these incremented values inside Details() method.
what does this statement mean?
your code below can not be compiled!
public class User{
static void Details()
{
public counter;
}
}
if you want to use reflection to send args to method ,why not just call User.Details(int a,int b)

Let a constructor access a static variable

Right now I have two .java files.
The Main.java:
public class Main {
static int integer = 15;
NeedInteger need = new NeedInteger();
}
and the NeedInteger.java
public class NeedInteger {
System.out.println(integer);
}
This is of course very simplified, but is there any way I can accomplish this?
As many have answered, the correct method is to pass the value in to the constructor of the new class.
If for some reason you cannot do that, then you can use a public static accessor method in Main to access the value (this would be slightly better than just making the field public).
E.g.
public class Main
{
private static int integer = 15;
public static int getInteger()
{
return integer;
}
}
public class NeedInteger
{
public NeedInteger()
{
int integer = Main.getInteger();
}
}
Add a constructor to NeedInteger (and optionally a member if you need to also store it):
public class NeedInteger {
private int integer;
public NeedInteger(int integer) {
this.integer = integer;
System.out.println(integer);
}
}
Then pass your value when you create the instance:
public class Main {
static int integer = 15;
NeedInteger need = new NeedInteger(integer);
}
You would have to do some bad juju moves (like using a global variable) or pass it to the constructor.
NOTE: your
public class NeedInteger {
System.out.println(integer);
}
has no method in it. I would recommend all this to be rewritten as such:
public Class NeedInteger {
NeedInteger(int integer) {
System.out.println(integer);
}
}
If you really want the work to be done on construction.
EDIT: From your comment above.
Instead, have the class structured so:
public Class NeedStringArray {
NeedStringArray(String[][][] stringArr) {
//work with String array here
}
}
That has no real additional overhead, since the actual array will not be passed, but only a reference to it. You WILL likely want to set the array to be final or something, to avoid it being edited in the NeedStringArray constructors.
integer is private, so it cannot be accessed by NeedInteger. you'll have to make it public or use a setter or getter and you'll need to use Main.integer since it's static.
Generally, you set in the Constructor.
Pass in the variable to the class constructor.
An array reference would be just that--a reference.
Or you could pass in the class itself, or use a static (meh).
Per your comment I'd say you can either host your array in a singleton
or as others suggested have the second class accept the reference to the array in the constructor. You can then use Dependency Injection framework (e.g. Guice) to get wire them up

Categories