This question has been asked here. As per the answer :
private final int NUMBER = 10;
If it cannot change, there is no point having one copy per instance.
My doubt is what if instance of the class is created, say once a day and it lasts around a few seconds. Is it good idea to keep the int(in some case object) in memory?
Assuming, there can be many (20-30) such objects.
How you store the information depends very much on what it is intended to be used for.
There are a few approaches you might take:
private static final
This is a good choice if the value will never be modified during the lifetime of the application. It means, when you're creating your multiple instances, you are only actually storing this particular variable ONCE.
private final
This is meant for those times when the value might take on different values for different instances of your object, but any specific instance will not have it's value modified throughout the object's life time.
If you're looking at something which might take on different values over a range of time, then this might be of interest to you.
public static int GetNumber(){...}
Another approach you might consider is to have a static method return the value you are after. This makes it easy to deal with changes in the value, but you also need to consider the effect of such a change throughout the lifetime of any given instance.
Hope that helps...
Regarding private final int number, your claim that
If it cannot change, there is no point having one copy per instance
is absolutely wrong. Consider this code, typical of an immutable class:
private final int number;
public MyClass(int number) {
this.number = number;
}
There are many instances of this pattern in the JDK, and in production code classes around the globe.
To answer your question about performance, I doubt you could measure the difference between using static vs instance constants.
Related
public class DataEvent {
private static final AtomicInteger lastRevision = new AtomicInteger();
private final int revision;
private final long threadId;
private final long timestamp;
private DataEvent(int revision) {
this.revision = revision;
this.threadId = Thread.currentThread().getId();
this.timestamp = System.nanoTime();
}
public static DataEvent newInstance() {
return new DataEvent(lastRevision.incrementAndGet());
}
}
My questions are following:
is it absolutely correct to say that all objects will be constructed consistently one by one? I mean that every new object is constructed later then previous one. In other words each new object has timestamp that is bigger then previous one.
how final keyword affects this behavior? As I understand if all object fields are final then it makes constructor atomic in some way. Reference is not published until all final fields are initialized.
what is best practice to construct such objects? Is is enough to make lastRevision atomic or newInstance should be declared as synchronized?
is it absolutely correct to say that all objects will be constructed
consistently one by one
No. lastRevision.incrementAndGet() is a blocking call but the scheduler could pause the first thread after receiving the first ID then resume the it after the second thread receives the second ID, meaning both constructors would execute concurrently.
In other words each new object has timestamp that is bigger then
previous one.
No, see above.
how final keyword affects this behavior?
It doesn't.
As I understand if all object fields are final then it makes
constructor atomic in some way
Incorrect. If every field is final then a class is immutable* which makes it implicitly thread-safe.
what is best practice to construct such objects? Is is enough to make
lastRevision atomic or newInstance should be declared as synchronized?
If every instance must be created serially then newInstance should be synchronized. Once it is, there's no point in the atomic integer. Even if you do this, the timestamp might still be the same, depending on the resolution of the underlying system clock.
* well, not exactly. If every field is final and is also immutable itself.
The atomicity guarantees are only valid for incrementAndGet() call. So yes, the revisions will be consecutive for every new object, which is the purpose of the atomic datatypes. So, to answer your question: There is no guarantee that the multiple threads will execute the statements within the constructor in the same order as they invoke incrementAndGet(). To achieve this you will have to put this section inside a synchronized block.
finals do not help here. They're purely logical feature which doesn't allow to mutate the field after object creation.
If you really need the timestamps to be aligned with revisions, you have to introduce some form of thread synchronization. You can make the whole method synchronized and then the lastRevision doesn't have to be atomic.
Also, whatever you decide to do you might also want to check on guarantees provided by System.nanoTime() itself. Click.
I'm curious how are the static final fields treated by the JVM. I saw a similar question here but it's not what I'm looking for. Let's consider such example:
public class TestClassX {
public final int CODE_A = 132;
public final int CODE_B = 948;
public final int CODE_C = 288;
// some other code
}
public class TestClassY {
public static final int CODE_A = 132;
public static final int CODE_B = 948;
public static final int CODE_C = 288;
// some other code
}
In TestClassX fields, as they are final and cannot be modified, have the same values in all instances of the TestClassX class. Of course I cannot write TestClassX.CODE_A but I can say, that these values are actually common for all instances - I'm sure, that each instance has a CODE_A field with the value 132.
In the TestClassY I can use the syntax TestClassY.CODE_A, but at a first sight it's only easier for a developer who sees "Oh, those values are common for all instances".
My main question:
I guess that JVM, in case of TestClassX, doesn't use any extra memory for final fields each time a new instance is created. Does it? Does JVM make any optimization in this case and what kind of optimization it is?
Extra question 1) I'm also sure that I'm missing something very important here which is the cause of my doubts. What's that?
Extra question 2) Btw. How can I take a look at how my Java source code looks like after the JVM optimization (so I can use in in the future ;))? Does any IDE support such a functionality? IntelliJ for example? I would like simply to see how JVM treats my TestClassX and TestClassY.
Non-static fields are always present in the instances. They do not save memory.
In general JVM does not optimize non-static fields. Even if they are final they can be still set to different value using reflection or during deserialization.
There is an experimental VM option -XX:+TrustFinalNonStaticFields (off by default) which tells JVM to optimize access to such fields, i.e. treat them as constants and eliminate field loads.
There is a -XX:+PrintAssembly VM option to dump JIT-compiled code.
For the first part of your question, maybe this answer can help you.
For the second part you could see the generated assembly (as stated in this answer) by adding -XX:+PrintOptoAssembly flag when you run/compile your code.
I should also add that the assembly code given to you is not the real opcode generated by the jvm, but the code needed to be run under your
actual architecture.
Hope this helps!
I used to define a set of related constants like Bundle keys together in an interface like below:
public interface From{
String LOGIN_SCREEN = "LoginSCreen";
String NOTIFICATION = "Notification";
String WIDGET = "widget";
}
This provides me a nicer way to group related constants together and used them by making a static import (not implements). I know Android framework also uses the constants in same way like Toast.LENTH_LONG, View.GONE.
However, I often feel that the Java Enums provide much better and powerful way to represent the constant.
But is there a performence issue in using enums on Android?
With a bit of research I ended up in confusion. From this question
"Avoid Enums Where You Only Need Ints” removed from Android's performance tips? it's clear that Google has removed "Avoid enums" from its performance tips, but from it's official training docs Be aware of memory overhead section it clearly says: "Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android." Is this still holds good? (say in Java versions after 1.6)
One more issue that I observed is to send enums across intents using Bundle I should send them by serializing (i.e putSerializable(), that I think an expensive operation compared to primitive putString() method, eventhough enums provides it for free).
Can someone please clarify which one is the best way to represent the same in Android? Should I strictly avoid using enums on Android?
Use enum when you need its features. Don't avoid it strictly.
Java enum is more powerful, but if you don't need its features, use constants, they occupy less space and they can be primitive itself.
When to use enum:
type checking - you can accept only listed values, and they are not continuous (see below what I call continuous here)
method overloading - every enum constant has its own implementation of a method
public enum UnitConverter{
METERS{
#Override
public double toMiles(final double meters){
return meters * 0.00062137D;
}
#Override
public double toMeters(final double meters){
return meters;
}
},
MILES{
#Override
public double toMiles(final double miles){
return miles;
}
#Override
public double toMeters(final double miles){
return miles / 0.00062137D;
}
};
public abstract double toMiles(double unit);
public abstract double toMeters(double unit);
}
more data - your one constant contains more than one information that cannot be put in one variable
complicated data - your constant need methods to operate on the data
When not to use enum:
you can accept all values of one type, and your constants contain only these most used
you can accept continuous data
public class Month{
public static final int JANUARY = 1;
public static final int FEBRUARY = 2;
public static final int MARCH = 3;
...
public static String getName(final int month){
if(month <= 0 || month > 12){
throw new IllegalArgumentException("Invalid month number: " + month);
}
...
}
}
for names (like in your example)
for everything else that really doesn't need an enum
Enums occupy more space
a single reference to an enum constant occupies 4 bytes
every enum constant occupies space that is a sum of its fields' sizes aligned to 8 bytes + overhead of the object
the enum class itself occupies some space
Constants occupy less space
a constant doesn't have a reference so it's a pure data (even if it's a reference, then enum instance would be a reference to another reference)
constants may be added to an existing class - it's not necessary to add another class
constants may be inlined; it brings extended compile-time features (such as null checking, finding dead code etc.)
If the enums simply have values, you should try to use IntDef/StringDef , as shown here:
https://developer.android.com/studio/write/annotations.html#enum-annotations
Example: instead of :
enum NavigationMode {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS}
you use:
#IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
#Retention(RetentionPolicy.SOURCE)
public #interface NavigationMode {}
public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;
and in the function that has it as a parameter/returned value , use:
#NavigationMode
public abstract int getNavigationMode();
public abstract void setNavigationMode(#NavigationMode int mode);
In case the enum is complex, use an enum. It's not that bad.
To compare enums vs constant values, you should read here:
http://hsc.com/Blog/Best-Practices-For-Memory-Optimization-on-Android-1
Their example is of an enum with 2 values. It takes 1112 bytes in dex file compared to 128 bytes when constant integers are used . Makes sense, as enums are real classes, as opposed to how it works on C/C++ .
With Android P, google has no restriction/objection in using enums
The documentation has changed where before it was recommended to be cautious but it doesn't mention it now.
https://developer.android.com/reference/java/lang/Enum
In addition to previous answers, I would add that if you are using Proguard (and you should definitely do it to reduce size and obfuscate your code), then your Enums will be automatically converted to #IntDef wherever it is possible:
https://www.guardsquare.com/en/proguard/manual/optimizations
class/unboxing/enum
Simplifies enum types to integer constants, whenever possible.
Therefore, if you have some discrete values and some method should allow to take only this values and not others of the same type, then I would use Enum, because Proguard will make this manual work of optimizing code for me.
And here is a good post about using enums from Jake Wharton, take a look at it.
As a library developer, I recognize these small optimizations that should be done as we want to have as little impact on the consuming app's size, memory, and performance as possible. But it's important to realize that [...] putting an enum in your public API vs. integer values where appropriate is perfectly fine. Knowing the difference to make informed decisions is what's important
Should I strictly avoid using enums on Android?
No. "Strictly" means they are so bad, they should not be used at all. Possibly a performance issues might arise in an extreme situation like many many many (thousands or millions of) operations with enums (consecutive on the ui thread). Far more common are the network I/O operations that should strictly happen in a background thread.
The most common usage of enums is probably some kind of type check - whether an object is this or that which is so fast you won't be able to notice a difference between a single comparison of enums and a comparison of integers.
Can someone please clarify which one is the best way to represent the same in Android?
There is no general rule of thumb for this. Use whatever works for you and helps you get your app ready. Optimize later - after you notice there's a bottleneck that slows some aspect of your app.
I like to add, that you can not use #Annotations when you declare a List<> or Map<> where either key or value is of one of your annotation interfaces.
You get the error "Annotations are not allowed here".
enum Values { One, Two, Three }
Map<String, Values> myMap; // This works
// ... but ...
public static final int ONE = 1;
public static final int TWO = 2;
public static final int THREE = 3;
#Retention(RetentionPolicy.SOURCE)
#IntDef({ONE, TWO, THREE})
public #interface Values {}
Map<String, #Values Integer> myMap; // *** ERROR ***
So when you need to pack it into a list/map, use enum, as they can be added, but #annotated int/string groups can not.
Two facts.
1, Enum is one of the most powerful feature in JAVA.
2, Android phone usually has a LOT of memory.
So my answer is NO. I will use Enum in Android.
Consider the class Foo.
public class Foo {
private double size;
public double getSize() {
return this.size; // Always O(1)
}
}
Foo has a property called size, which is frequently accessed, but never modified, by a given method. I've always cached a property in a variable whenever it is accessed more than once in any method, because "someone told me so" without giving it much thought. i.e.
public void test(Foo foo) {
double size = foo.getSize(); // Cache it or not?
// size will be referenced in several places later on.
}
Is this worth it, or an overkill?
If I don't cache it, are modern compilers smart enough to cache it themselves?
A couple of factors (in no particular order) that I consider when deciding whether or not to store the value returned by a call to a "get() method":
Performance of the get() method - Unless the API specifies, or unless the calling code is tightly coupled with the called method, there are no guarantees of the performance of the get() method. The code may be fine in testing now, but may get worse if the get() methods performace changes in the future or if testing does not reflect real-world conditions. (e.g. testing with only a thousand objects in a container when a real-world container might have ten million) Used in a for-loop, the get() method will be called before every iteration
Readability - A variable can be given a specific and descriptive name, providing clarification of its use and/or meaning in a way that may not be clear from inline calls to the get() method. Don't underestimate the value of this to those reviewing and maintaining the code.
Thread safety - Can the value returned by the get() method potentially change if another thread modifies the object while the calling method is doing its thing? Should such a change be reflected in the calling method's behavior?
Regarding the question of whether or not compilers will cache it themselves, I'm going to speculate and say that in most cases the answer has to be 'no'. The only way the compiler could safely do so would be if it could determine that the get() method would return the same value at every invocation. And this could only be guaranteed if the get() method itself was marked final and all it did was return a constant (i.e an object or primitive also marked 'final'). I'm not sure but I think this is probably not a scenario the compiler bothers with. The JIT compiler has more information and thus could have more flexibility but you have no guarantees that some method will get JIT'ed.
In conclusion, don't worry about what the compiler might do. Caching the return value of a get() method is probably the right thing to do most of the time, and will rarely (i.e almost never) be the wrong thing to do. Favor writing code that is readable and correct over code that is fast(est) and flashy.
I don't know whether there is a "right" answer, but I would keep a local copy.
In your example, I can see that getSize() is trivial, but in real code, I don't always know whether it is trivial or not; and even if it is trivial today, I don't know that somebody won't come along and change the getSize() method to make it non-trivial sometime in the future.
The biggest factor would be performance. If it's a simple operation that doesn't require a whole lot of CPU cycles, I'd say don't cache it. But if you constantly need to execute an expensive operation on data that doesn't change, then definitely cache it. For example, in my app the currently logged in user is serialized on every page in JSON format, the serialization operation is pretty expensive, so in order to improve performance I now serialize the user once when he signs in and then use the serialized version for putting JSON on the page. Here is before and after, made a noticeable improvement in performance:
//Before
public User(Principal principal) {
super(principal.getUsername(), principal.getPassword(), principal.getAuthorities());
uuid = principal.getUuid();
id = principal.getId();
name = principal.getName();
isGymAdmin = hasAnyRole(Role.ROLE_ADMIN);
isCustomBranding= hasAnyRole(Role.ROLE_CUSTOM_BRANDING);
locations.addAll(principal.getLocations());
}
public String toJson() {
**return JSONAdapter.getGenericSerializer().serialize(this);**
}
// After
public User(Principal principal) {
super(principal.getUsername(), principal.getPassword(), principal.getAuthorities());
uuid = principal.getUuid();
id = principal.getId();
name = principal.getName();
isGymAdmin = hasAnyRole(Role.ROLE_ADMIN);
isCustomBranding= hasAnyRole(Role.ROLE_CUSTOM_BRANDING);
locations.addAll(principal.getLocations());
**json = JSONAdapter.getGenericSerializer().serialize(this);**
}
public String toJson() {
return json;
}
The User object has no setter methods, there is no way the data would ever change unless the user signs out and then back in, so in this case I'd say it is safe to cache the value.
If the value of size was calculated each time say by looping through an array and thus not O(1), caching the value would have obvious benefits performance-wise. However since size of Foo is not expected to change at any point and it is O(1), caching the value mainly aids in readability. I recommend continuing to cache the value simply because readability is often times more of a concern than performance in modern computing systems.
IMO, if you are really worried about performance this is a bit overkill or extensive but there is a couple of ways to ensure that the variable is "cached" by your VM,
First, you can create final static variables of the results (as per your example 1 or 0), hence only one copy is stored for the whole class, then your local variable is only a boolean (using only 1 bit), but still maintaining the result value of double (also, maybe you can use int, if it is only 0 or 1)
private static final double D_ZERO = 0.0;
private static final double D_ONE = 1.0;
private boolean ZERO = false;
public double getSize(){
return (ZERO ? D_ZERO : D_ONE);
}
Or if you are able to set the size on initialization of the class you can go with this, you can set the final variable through constructor, and static, but since this is a local variable you can go with the constructor:
private final int SIZE;
public foo(){
SIZE = 0;
}
public double getSize(){
return this.SIZE;
}
this can be accessed via foo.getSize()
In my code, i would cache it if either the getSize() method is time consuming or - and that is more often - the result is used in more or less complex expressions.
For example if calculating an offset from the size
int offset = fooSize * count1 + fooSize * count2;
is easier to read (for me) than
int offset = foo.getSize() * count1 + foo.getSize() * count2;
From the famous book Java Concurrency in Practice chapter 3.4.1 Final fields
Just as it is a good practice to make all fields private unless they
need greater visibility[EJ Item 12] , it is a good practice to make
all fields final unless they need to be mutable.
My understanding of final references in Java : A final reference/ field just prevents the the field from getting re initialized but if it references a mutable object , we can still change its state rendering it mutable . So I am having difficulty understanding the above quote . What do you think ?
final fields prevent you from changing the field itself (by making it "point" to some other instance), but if the field is a reference to a mutable object, nothing will stop you from doing this:
public void someFunction (final Person p) {
p = new Person("mickey","mouse"); //cant do this - its final
p.setFirstName("donald");
p.setLastName("duck");
}
the reference p above is immutable, but the actual Person pointed to by the reference is mutable.
you can, of course, make class Person an immutable class, like so:
public class Person {
private final String firstName;
private final String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
//getters and other methods here
}
such classes once created, cannot be modified in any way.
This quote says only what is says:
make all fields final unless they need to be mutable
mutable field is a field that you can later change to point to another object. If the field is final, it can still reference mutable object (e.g. java.util.Date). Thus the field is immutable (always points to the same object), but this object is mutable.
in java final is similer to this:
int *const p=&something //constant pointer.in c++. you can't use this pointer to change something but that something can be changed with its own.
in java final fields can't be changed but the object to who they refer may change by its own .
Ex. 'this' is final you can't assign anything to this but you can assign to object to whom this refer.
From your Ques:
it is a good practice to make all fields final unless they need to be mutable.
to just avoid any modification(either logically or accidently) to original it's always good to make them final.
As per Java code convention final variables are treated as constant and written in all Caps e.g.
private final int COUNT=10; // immutable -> cannot be changed
Making a collection reference variable final means only reference can not be changed but you can add, remove or change object inside collection. For example:
private final List Loans = new ArrayList();
list.add(“home loan”); //valid
list.add("personal loan"); //valid
loans = new Vector(); //not valid
Read more: http://javarevisited.blogspot.com/2011/12/final-variable-method-class-java.html#ixzz2KP5juxm0
To answer your question: Yes, if you use them correctly.
Disregard the quote. There's little to no benefit from making your code blotted with final's every now and then. Author aimed for a good practice, but in large code-bases, seeing everything made final rather obscures the intent, making reading code harder and more obscure - and may give little to no benefit.
Two approaches
Generally though, there are two schools. Choose yours:
AGAINST, unless really needed
One is NOT to use final, unless you REALLY want those reading the code you wrote to know that this field is special in some way and is not to be trifled with.
For, there's never a bad place to use final!
The other is enamored with final and wants it everywhere. It's less prevalent. Renauld Waldura makes for an excellent propagator of the idea. Read his linked entry, titled "Final word on final keyword", it's a good and in-depth read.
May depend on Java you use
On my part I'd just want you to know that final changed, and doesn't ALWAYS mean unmutable, as you can read in Heinz Kabutz' Java Specialist Newsletter. He takes you through how it worked in different Javas, feel free to take his code and check the Java you use.