Is it considered good practice to assign a value to a member variable outside of any function?
I was always taught what you declare above and initialize internally. It's more efficient to initialize things inside a constructor because if you need to change it with a passed parameter when building, you initialize and assign when you can just initialize.
Example:
public class TestClass{
//Declared but uninitialized
Object obj;
//Makes no difference but easier to read
public TestClass(){
this.obj = new Object();
}
//In this constructor however the object being passed in is what is initializing obj
//-so if you were to initialize it above and then change it down here you are writing
//-to the mem twice and it is less efficient.
public TestClass(Object arg){
this.obj = (Object)arg;
}
}
The caveat with this is that memory is REALLY cheap these days. The only real purpose of doing it this way (other than not wanting to look like a rookie) is to make her manageable by other people.
source to share
Initialization of an object in a declaration can be done if the program "always" needs an instance of the object, and the cost of creating an instance is not too high (time, resources). Then yes, this type of "eager initialization" may be desirable.
However, this construct goes against OO design as the classes are not related to each other and make unit tests more rigid.
In the example:
public class App {
private Car car = new Car();
}
You speak:
- The application will always need a Car object.
- The car will always be created after the application is instantiated. (This can be problematic if the car instance is expensive IE, it also has multiple objects that are instantiated and is said to load data from a remote call of some kind).
Ideally, you would like to create an object when you really need it. Or in a constructor (default or overloaded) to provide some flexibility.
public class App {
private Car car;
App() {
}
// overloaded constructor
App(Car car) {
this.car = car;
}
public void setCar(Car car) {
this.car = car;
}
public Car getCar() {
return car;
}
public static void main(String[] args) {
// default constructor, lightweight, no car initialization happening;
App ap1 = new App();
// Ok, now I want a car, and it should be red.
Car redCar = new Car("red");
ap1.setCar(redCar);
// Using overloaded constructor, now I can control aspects of "car"
Car blueCar = new Car("blue");
App ap2 = new App(blueCar);
}
}
source to share
If you want your code to be easier to test, this is bad practice. The reason is that creation App
will also create Car
whether you want it or not. Now if Car
has code that connects to the database, oops, now that you are testing App
, you need to have an accessible database that you can connect to, or your test will fail.
The solution is dependency injection like inversion of control. You should write it like this:
public class App {
private Car car;
public App(Car car) {
this.car = car;
}
public static void main(String[] args) {
// TO DO
}
}
Now the creature App
does not necessarily create Car
, and they are less connected.
Now I am very pedantic. I probably always use your example in my code. I'm just pointing out the flaw. This is not ALWAYS bad or ALWAYS good.
source to share
private car = new car ();
This is fine normal IMHO. Several reasons not to do this:
-
Car.<init>
need arguments available only inApp.init
-
App
has many fields and others must be initialized toApp.<init>
, and for consistency you want to keep them all together.
Don't do the following anyway:
private car car = null;
As every java developer knows that instance fields are initialized to null
.
source to share
please note that there is a difference in meaning between:
public class App {
private Car car = new Car();
public static void main(String[] args) {
// TO DO
}
}
and
public class App {
private Car car;
public App(){
car = new Car();
}
}
If, for example, if the first car () fails in the first, then you will surely have fun debugging that. Secondly, it's much more readable and debuggable if needed. If you think of fields as chunks for a plan for a class, then there is no point in initializing them in your declaration. Since you have basic here, this is probably your entry point, but for other classes, if you think of them as blueprints for objects, the idea of constructors makes a lot of sense:
public class App{
private Car car;
public Car getCar(){
return car;
}
public void setCar(Car car){
this.car = car;
}
public App(Car car){
this.car = car;
}
}
This, I believe, is the most common structure for oop classes.
source to share
The ideal way to execute this code would be to create an App object in the main method that will call the constructor for the Car class. Thus, the code will look like this.
public class {
private Car car;
public static void main(String[] args)
{
App app=new App(); //
app.car. //Followed by the method or the member variable that you would like to
//access
}
}
source to share
Use the Init () method for all initialization.
public class App {
private Car car;
public App() {
this.car = null;
}
public void Init() {
this.car = new Car();
}
public void Shutdown() {
this.car = null;
}
public static void main(String[] args) {
App app = new App();
app.Init();
app.Shutdown();
app = null;
}
}
source to share