The following code simply subtracts a value (10 in this case, just for the demonstration) from the current year obtained by using the java.util.Calendar class.
public final class Test
{
private static final Test TEST = new Test();
private static final int YEAR = Calendar.getInstance().get(Calendar.YEAR);
private final int eval=YEAR - 10;
public static void main(String[] args)
{
System.out.println("Evaluation "+TEST.eval);
}
}
I expect this code to display 2003 (current year - 10) but instead, it displays -10. I assume the constant YEAR hasn't been initialized. Why does this happen in this case?
This happens because you are initializing Test before you have initialized YEAR - meaning it will go to the (implicit) constructor and initialize eval to YEAR-10 before YEAR has a value (so it defaults to 0).
As denoted in the comments, simply changing the order of YEAR and TEST in the initialization will do the trick.
Because it's not static - you have to create an object in order to use this field! (or change it to static)
Try:
public final class Test
{
private static final Test TEST = new Test();
private static final int YEAR = Calendar.getInstance().get(Calendar.YEAR);
private final int eval=YEAR - 10;
public static void main(String[] args)
{
Test t = new Test();
System.out.println("Evaluation "+t.eval);
}
}
Make eval static and it will work. If you do not want it static, then do the computation in the main method.
As others have mentioned, the problem is in the order of the static fields. But, you can avoid the ordering problem entirely by lazily initializing TEST using a method (like is done in the singleton pattern):
public final class Test
{
private static Test TEST = null;
private static final Test getInstance() {
if (TEST == null) {
TEST = new Test();
}
return TEST;
}
private static final int YEAR = Calendar.getInstance().get(Calendar.YEAR);
private final int eval=YEAR - 10;
public static void main(String[] args)
{
System.out.println("Evaluation "+Test.getInstance().eval);
}
}
Related
I was writing this piece of code to understand reflection and encountered one scenario where I couldn't really figure out the reason for the codes' behavior. Hopefully I receive some guidance from the community.
Following is my test model class & here, for every instantiation, I want to know the exact number of instances created during runtime (using reflection)
public final class Model {
private static final Model instance = new Model("Testing");
private static int count = 0;
private String name;
private Model(String name) {
this.name = name;
++count;
}
public static Model getInstance() {
return instance;
}
public static int getInstanceCount() {
return count;
}
public String getName() {
return name;
}
public void doSomething() {
try {
System.out.println("Shh.... I am trying to do something");
Thread.sleep(1000);
System.out.println("Ok! Done.");
return;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Oops! I failed in doing your job...");
}
}
The driver code for this scenario is as follows,
public class ReflectionTest {
public static void main(String[] args) throws Exception {
Model.getInstance().doSomething();
System.out.println(Model.getInstanceCount());
Constructor<?>[] constructor = Model.class.getDeclaredConstructors();
for (Constructor<?> aConstructor : constructor) {
aConstructor.setAccessible(true);
Model m = (Model) aConstructor.newInstance("Testing through Reflection");
System.out.println(m.getName());
m.doSomething();
System.out.println(m.getInstanceCount());
//System.out.println(Model.getInstanceCount());
}
}
}
The output for this above piece of code came out to be as follows,
Shh.... I am trying to do something
Ok! Done.
0
Testing through Reflection
Shh.... I am trying to do something
Ok! Done.
1
As you can see, the instance count came out to be 1. I expected it to be as 2.
However, I changed the test model class's constructor as shown below. The datatype of count is now changed to Integer, instead of previously set 'int'.
private Model(String name) {
this.name = name;
if (count == null)
count = 0;
++count;
}
Surprisingly, I get the correct value for the instance count.
Shh.... I am trying to do something
Ok! Done.
1
Testing through Reflection
Shh.... I am trying to do something
Ok! Done.
2
This might be a silly question, but I am not able to ponder on what really happened behind the scenes. I need some guidance from the community on this.
Thanks in advance.
This has nothing to do with reflection.
private static final Model instance = new Model("Testing");
private static int count = 0;
The initializers are executed in order. So:
private static final Model instance = new Model("Testing");
Executing the constructor causes count to be incremented from 0 to 1, but then:
private static int count = 0;
Sets count back to zero.
Reverse the order of the declarations.
private static int count = 0;
private static final Model instance = new Model("Testing");
Or omit the initializer on count (its default value is zero anyway).
private static final Model instance = new Model("Testing");
private static int count;
I'm kind of mediocre at Java at the moment, and new to JUnit, but I can't find the answer to this question elsewhere.
I want to use a constant variable defined within the class I am testing, within the Junit test case itself, but since it's a static final, it's not available.
The class I'm testing is as follows:
public class MyClass {
private static final int HSIZE = 7;
private static final int NUM_LOCS = 3;
.
.
.
void generateRandomLocations() {
Random rand = new Random();
String[] hPos = new String[NUM_LOCS];
for (int i=0; i<NUM_LOCS; i++) {
hPos[i] = Integer.toString(rand.nextInt(HSIZE));
}
setLocations(hPos);
}
}
Simple enough, and it seems to work OK, but I'd like to add a test case in JUnit - something like the following:
#Test
void testGenerateRandomLocations() {
MyClass mc = new MyClass();
mc.generateRandomLocations();
String[] check = mc.getLocations();
assertEquals(sadc.NUM_LOCS, check.length);
}
(The getter is defined, I just haven't included it here for brevity)
However (of course) sadc.NUM_LOCS is not available because it's only visible in MyClass.
How can I access this from a JUnit (5) test case?
I've used #VisibleForTesting annotation which annotates why normally private variables and methods are protected instead. They're not fully visible, but can be accessed for testing purposes. I've used this with what were private static final variables.
The example I've seen/worked with used a file called VisibleForTesting.java that contained:
package your.pkg.here;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.SOURCE;
/**
* Indicates that the class, method or field has greater
* visibility than otherwise needed to enhance testability.
*/
#Retention(SOURCE)
public #interface VisibleForTesting {
}
Then within the class you want to test you set the method or variable to protected, and use the #VisibleForTesting annotation:
public class MyClass {
private static final int HSIZE = 7;
#VisibleForTesting
protected static final int NUM_LOCS = 3;
void generateRandomLocations() {
Random rand = new Random();
String[] hPos = new String[NUM_LOCS];
for (int i=0; i<NUM_LOCS; i++) {
hPos[i] = Integer.toString(rand.nextInt(HSIZE));
}
setLocations(hPos);
}
}
This allows the tests to see it, but the variable is not available to the public, and there is an explanation for why it's not private. #VisibleForTesting can also be found in Google's Guava library, so you could include that instead of adding VisibleForTesting.java, but I haven't used that.
Have you try using Powermockito. Whitebox has getInternalState.
see if it helps
https://github.com/powermock/powermock/wiki/Bypass-Encapsulation
Simple answer
Make variable NUM_LOCS public. However, this is a poor design.
Better answer
Instead of static variable, pass NUM_LOCS through constructor:
public class MyClass {
private final int numLocs;
public MyClass(int numLocs) {
this.numLocs = numLocs;
}
//default ctor with default numLocs value
public MyClass() {
this.numLocs = 3;
}
//methods
}
Now, your test looks like this:
#Test
void testGenerateRandomLocations() {
int expectedNumLocs = 7;
MyClass mc = new MyClass(7);
mc.generateRandomLocations();
String[] check = mc.getLocations();
assertEquals(expectedNumLocs, check.length);
}
and you can make a test to check default value is 3, too:
#Test
void testGenerateRandomLocations() {
int expectedNumLocs = 3;
MyClass mc = new MyClass(); //no args
mc.generateRandomLocations();
String[] check = mc.getLocations();
assertEquals(expectedNumLocs, check.length);
}
I am using a class with only static variables to store all constants and run-time properties. But, recently I have seen instances when I'm referencing these variables, I get null.
Following is my class definition:
public class PlayerProperties {
// Runtime but constant properties
public static int screenHeight;
public static int screenWidth;
public static String androidId;
// Static properties
// Urls
public static final String baseUrl = "http://www.blynq.in/api/player/";
public static final String registerUrlAppender = "activationKeyValid";
public static final String schedulesUrlAppender = "getScreenData";
public static final String updateUrlAppender = "updateAvailable";
public static final String tokenRegisterUrl = "fcmRegister";
public static final String mediaStatsUrl = "mediaStats";
public static final String logsUrl = "logs";
public static final String pingUrl = "ping";
public static final String screenInfoUrl = "screenInfo";
// Developer Keys
public static final String youtubeDeveloperKey = "ABCDEFGH...";
// Folder structure
public static final String mediaFolder = "player/media";
public static final String imagesFolder = "player/media/images";
public static final String videosFolder = "player/media/videos";
public static final String pdfFolder = "player/media/pdf";
public static final String gifFolder = "player/media/gif";
public static final String webFolder = "player/media/web";
public static final String othersFolder = "player/media/others";
public static final String logsFolder = "player/logs";
public static final String defaultFolder = "player/default/";
public static final String serFolder = "player/ser/";
public static final String tempFolder = "player/temp/";
// Shared Prefs Keys
public static final String ANDROID_ID_KEY = "ANDROID_ID";
public static final String MY_PREFERENCES_KEY = "MyPrefs";
// General properties
public static final String dateTimeFormatString = "ddMMyyyyHHmmss";
public static final String dateFormatString = "yyyy-MM-dd";
// Timeouts
public static final int httpPollTimeout = 20000; // in millis
public static final int pingPeriodicity = 30; // in secs
public static final int updateCheckPeriodicity = 24; // in hrs
public static final int pushEnabledPollPeriodicity = 30; // in secs
public static final int pushDisabledPollPeriodicity = 30; // in secs
public static final int statsUploadPeriodicity = 60; // in mins
public static final int logsUploadPeriodicity = 24; // in hours
public static final int cleanupPeriodicity = 24; // in hours
public static final int registrationStatusRecheckPeriod = 20000; // in millis
public static final int tokenResendToServerPeriod = 20000; // in millis
// Others
public static final int maxTextHeight = 50; // in dp
...
}
I have not stored any reference instantiatin PlayerProperties class, as all variables contained within are static.
When I am referencing the variable androidId using PlayerProperties.androidId , I SOMETIMES get null.
I have initialized the variable in one of the activities:
PlayerProperties.androidId = sharedpreferences.getString(PlayerProperties.ANDROID_ID_KEY, String.valueOf(UUID.randomUUID()));
My suspicion is that garbage collector was kicked by android in between. If gc does kick in, would it knock off all my runtime-initialized static variables ?
Which memory segment are the static variables stored ?
If not, what else could be the issue ?
Extra details: My app is configured to automatically launches on boot. I am facing the above described issue only with low end processors and when app is automatically triggered on boot.
Please note the following in reference to above question:
Garbage collector removes only unreferenced objects. Static variables will lose their values only when they are unloaded from JVM during run-time.
Initialization happens when app is launched via activities. If there are any services/broadcast receivers that are accessing methods within other classes and use these ids, and the app is not yet running by that time, the uninitialized values are referenced as default value. In case of string - it is null.
Nothing to do with low-end processors, easy to blame them often but JVM is powerful enough.
Only public static String androidId; can be null, when you want to use it you should init it in this class or in some other class in onResume()
androidId is a reference to an string, string is a class that will get by default a null reference as intial value if you dont do it....
look at this taken from oracle's doc
So basically androidId is null because is not initialized....the fact that the variable is static or not is not relevant in this case...
see here for more details
...I SOMETIMES get null.
yes, you will get always null unless its value change at run time...
I trying to understand the difference between the two lines below. Why is it returning a zero when I add static to the field.
private static final int this_year = Calendar.getInstance().get(Calendar.YEAR);
From this I get: this_year = 0;
private final int this_year = Calendar.getInstance().get(Calendar.YEAR);
And from this I get: this_year = 2013;
Someone who can explain why the first returns a zero?
Here's the code I use it in:
public class TheKing {
public static final TheKing theKing = new TheKing();
private final int beltSize;
private static final int this_year = Calendar.getInstance().get(Calendar.YEAR);
private TheKing() {
beltSize = this_year - 1930;
}
public int beltSize() {
return beltSize;
}
public static void main(String[] args) {
System.out.println("TheKing wears a size " +
theKing.beltSize() + " belt.");
}
}
When fields are declared static, they are initialized in the static initialization method, meaning that your code looks like the following when compiled:
static {
theKing = new TheKing();
this_year = Calendar.getInstance().get(Calendar.YEAR);
}
Notice that the constructor is called before this_year is initialized, and before an int is initialized, it has its default value of 0. In other words, this_year is used before it is set to 2013.
One way to fix this is to simply reverse the order of the declarations:
private static final int this_year = Calendar.getInstance().get(Calendar.YEAR);
public static final TheKing theKing = new TheKing();
Static methods are initialized in the order they are given in code.
public static final TheKing theKing = new TheKing();
private static final int this_year = Calendar.getInstance().get(Calendar.YEAR);
So the above would initialize theKing first, which calls the constructor, which uses the uninitialized value of 0 of this_year. If you were to change it to:
private static final int this_year = Calendar.getInstance().get(Calendar.YEAR);
public static final TheKing theKing = new TheKing();
it would work fine.
Or if you remove the static, this_year would get initialized as the object theKing is created.
I am new to Android and from what I read here most of the question goes to Imageview setting image. Here is my problem same as ImageView errors
Ive created a arraylist of Integer because of some function needed Int List rather than String List. Basically like most of function I created it like this one
private ArrayList<Integer> myArrayList = new ArrayList<Integer>();
public void setPicture(Integer datanumber)
{
if (datanumber>=10)
{
myArrayList.add(R.drawable.picture);
}
else{
myArrayList.add(R.drawable.picture_gray);
}
///and so on
}
Everything works fine until I found out that I cannot get this string ex "R.drawable.picture" using this code
myArrayList.get(0).toString();
Instead it gives me random number that I cannot understand.
My question is how can I return it to default value(or the one that I add on my list)
Thank you for spending time reading my question
Use String.valueOf(myArrayList.get(0));
instead of myArrayList.get(0).toString();
It isn't giving you a Random number. It is giving you the value of R.drawable.picture. All resources in R.*.*are referenced through numbers. This is evident if you take a look inside R.java, which shows something like:
public final class R {
public static final class attr {
}
public static final class drawable {
public static final int help=0x7f020000;
public static final int ic_action_search=0x7f020001;
public static final int ic_launcher=0x7f020002;
public static final int splash1=0x7f020003;
}
public static final class id {
public static final int userName=0x7f070002;
}
public static final class layout {
public static final int splash=0x7f030003;
}
public static final class menu {
public static final int action=0x7f060000;
public static final int menu=0x7f060001;
}
public static final class string {
public static final int app_name=0x7f040000;
public static final int create_user=0x7f040004;
public static final int help=0x7f040001;
public static final int image=0x7f040002;
public static final int primarymodtext=0x7f040003;
}
}
What you are getting is the int value R.drawable.picture. This is because when you're adding a value to the array list, you're passing in the int value stored in R.drawable.picture.
You can still use this integer value you get like you would use R.drawable.picture. Just pass it in normally.