Where to initialize objects correctly?


I was taught that all variables and objects should be initialized in onCreate(), well, in the sense of global (as a rule).

But I have already met several times in the code of experienced developers when, for example, sheets are initialized right where the variables

private OnVideoSelectedListener mCallback;


private AdapterList mAdapterList = null;

private ArrayList<HashMap<String, String>> mTempVideoData = new ArrayList<>();
private ArrayList<HashMap<String, String>> mVideoData     = new ArrayList<>();

private String mNextPageToken = "";
private String mVideoIds = "";
private String mDuration = "00:00";

private boolean mIsStillLoading = true;

Not how much is it right and does it not interfere with anything? For example, the speed of the program or something else?

Author: Aleksey Timoshchenko, 2016-05-27

4 answers

Where to initialize objects correctly?

According to the documentation, there is only one requirement for initializing objects: Fields and variables must be initialized before they are used. So the answer is-anywhere.

I was taught that all variables and objects should be initialized in onCreate()...

I understand that the question is more about android. OnCreate() is a method that is intended for initialization Activity and it will be called as soon as you start the Activity with the intent. It is normal and common to initialize fields in the onCreate method. I think that the main idea to make the initialization of the Activity in onCreate is to reduce the start time of the application. When your app starts, android creates instances of all the classes (not sure about all of them) and if something takes a long time to run in the constructor, it will slow down the start of the app. This also applies to allocating memory for class fields. Although of course, this is a minuscule time.
But it is worth remembering that if you try to use Activity as

Activity activity = new Activity();
activity.someMethod()....

Then, the onCreate () method will not be called.

In general, regarding the question of where to initialize, the most common two ways are: - where the variable is declared
- in the constructor

Both are correct, I prefer constrctors. In any case, try to follow the same style.

For the sake of completeness of the answer, I note that you can also initialize the fields in the initialization block

class A {
    private String myField;
    {
        myField = "...";
    }
}
 10
Author: Mikhail Chibel, 2016-06-02 00:46:44

You can shoot through the leg when inheriting. Pseudocode:

class A {
   private List<Foo> items;
   public void onCreate(){
       items = new ArrayList<>();
   }

   public void onStart(){
       showList();
   }

   public void showList(){
       ((ListView)findViewById(R.id.listview)).setAdapter(new FooAdapter(items));
   }

   public void setItems(List<Foo> items){
       this.items.clear();
       this.items.addAll(items);
   }
}

class B extends A {
   @Override
   public void onCreate(){
       showList();
   }
}

class C extends A {
   @Override
   public void onCreate(){
       showList();
       super.onCreate();
   }
}

class D extends A {
   @Override
   public void onCreate(){
       setItems((List<Foo>)getIntent().getSerializable("list"));
       super.onCreate();
   }
}

If the initialization is moved to the declaration location (or in a non-static block, or in the constructor), the behavior of the program will become more predictable and there will be fewer options to break the base class.

 11
Author: Yura Ivanov, 2016-05-30 20:33:08

I found an interesting article, which describes five tips for optimizing code.

Tip #1. Whenever possible, use local variables instead of public class fields.

By limiting the scope of variables, you will not only improve the readability of the code and reduce the number of potential errors, but also make it better suited for optimization.

In the unoptimized code block shown below, the value the variable v is evaluated during the execution of the application. This is because this variable is available outside of the m() method and can be changed in any part of the code. Therefore, the value of the variable is unknown at the compilation stage. The compiler does not know whether calling the some_global_call() method will change the value of this variable or not, since the v variable, again, can be changed by any code outside the method.

In the optimized version of this example, v is a local variable. this means that its value can be calculated at the compilation stage. As a result, the compiler can put the value of the variable in the code it generates, which will help avoid calculating the value of the variable at runtime.

Unoptimized code:

class A {
  public int v = 0;

  public int m(){
    v = 42;
    some_global_call(); 
    return v*3; 
  }
}

Optimized code:

class A {
  public int m(){
    int v = 42;
    some_global_call();
    return v*3; 
  } 
}

Tip #2. Use the keyword final to tell the compiler that the value of the field is – constant

The final keyword can be used to protect the code from accidentally changing variables that should be constants. However, it allows you to improve performance, because it tells the compiler that it is a constant in front of it.

In a fragment of unoptimized code, the value of v*v*v must be calculated during program execution, since the value of v may change. In the optimized version, the use of the key the words final when declaring a variable and assigning it a value, tells the compiler that the value of the variable will not change. Thus, the value can be calculated at the compilation stage and the value will be added to the output code, rather than commands to calculate it during program execution.

Unoptimized code:

class A {
  int v = 42;

  public int m(){
    return v*v*v;
  } 
}

Optimized code:

class A {
  final int v = 42;

  public int m(){
    return v*v*v;  
  } 
}

Tip #3. Use the keyword final when declaring classes and methods

Since any method in Java can be polymorphic, declaring a method or class with the keyword final indicates to the compiler that the method is not overridden in any of the subclasses.

In the unoptimized version of the code before calling the function m() you need to resolve it. In optimized code, due to the use of the m() keyword when declaring the final method, the compiler knows which one it is the version of the method will be called. Therefore, it can avoid searching for the method and replace the method call m() with its contents, embedding it in the desired location of the program. As a result, we get an increase in performance.

Unoptimized code:

class A {
  public int m(){
    return 42;  
  } 
  public int f(){
    int sum = 0; 
    for (int i = 0; i < 1000; i++)
      sum += m(); // m must be resolved before making a call 
    return sum;
  }
}

Optimized code:

class A {
  public final int m(){
    return 42;  
  } 
  public int f(){
    int sum = 0; 
    for (int i = 0; i < 1000; i++)
      sum += m();  
    return sum;
  } 
}

Tip #4. Avoid calling small methods via JNI

There are good reasons to use JNI calls. For example, if you have you have C/C++ code or libraries that you want to reuse in Java applications. Perhaps you are building a cross-platform application, or your goal is to increase performance by using low-level mechanisms. However, it is important to keep the number of JNI calls to a minimum, as each of them creates a significant load on the system. When JNI is used to optimize performance, this additional load can negate the expected benefit. In particular, frequent calls to short, non-computationally intensive JNI methods can degrade performance. And if such calls are placed in a loop, then the unnecessary load on the system will only increase.

Sample code:

class A {
  public final int factorial(int x){
    int f = 1;
    for (int i =2; i <= x; i++)
      f *= i;
    return f;  
  } 
  public int compute (){
    int sum = 0; 
    for (int i = 0; i < 1000; i++)
      sum += factorial(i % 5); 
// if we used the JNI version of factorial() here
// it would be noticeably slower, because it is in a loop
// and the loop amplifies the overhead of the JNI call
    return sum;
  }
}

Tip #5. Use standard libraries instead of implementing the same functionality in your own code

The Java standard libraries are heavily optimized. If use the internal mechanisms of Java wherever possible, this will achieve the best performance. Standard solutions can work much faster than "self-written" implementations. Trying to avoid additional load on the system by not calling a standard library function can actually degrade performance. The unoptimized version of the code shows an attempt to avoid calling the standard function Math.abs() at the expense of its own implementations of the algorithm for obtaining the absolute value of a number. However, the code in which the library function is called runs faster due to the fact that the call is replaced by an optimized internal implementation in ART at compile time.

Unoptimized code:

class A {
  public static final int abs(int a){
    int b;
    if (a < 0) 
      b = a;
    else
      b = -a;
    return b;
  } 
}

Optimized code:

class A {
  public static final int abs (int a){
    return Math.abs(a); 
  } 
}

P.S. I hope at least something helped.

 10
Author: iFr0z, 2018-11-21 13:01:42

Your question is quite abstract. In fact, I can note that this does not affect anything critically, collectibles are initialized immediately so as not to forget later, since even the methods of an uninitialized collection will be skipped by the compiler,and then NPE will crash. In fact, initialization of these variables will occur before the onCreate method starts working, and will increase the time between calling the activity (for example, from another activity) and starting the onCreate method. But this difference is negligible. To feel for example, you need to initialize hundreds of thousands of global variables. So if you do not find fault with the words, it does not interfere with anything. In it onCreate, initialization is also done because there you can already access various data(for example, which were transmitted via Extra, etc.)...)

 4
Author: Eugene Troyanskii, 2016-05-27 22:51:40