This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Should I initialize variable within constructor or outside constructor
I was wondering, which is a better practice and why. Should I initialize class fields upon declaration, or should I do it in the constructor? Given that it's a simple one-line initialization.
class Dude
{
String name = "El duderino";
Dude() {
// irrelevant code
}
}
vs.
class Dude
{
String name;
Dude() {
name = "El duderino";
// irrelevant code
}
}
Edit: I am aware of the situations where one of the styles would be preferred over the other like in the case of executing initializer code that might throw an exception. What I'm talking about here are cases when both styles are absolutely equivalent. Both ways would accomplish the same task. Which should I use then?
If the member can only be set via an accessor (a "setter" method), I prefer the first style. It provides a hint that the initialized value is the default upon construction.
If the member can be specified during construction, I generally pass the default value to an appropriate constructor from constructor with fewer parameters. For example,
final class Dude {
private final String name;
Dude() {
this("El Duderino");
}
Dude(String name) {
this.name = name;
}
}
The first one is used usually to initialize static variable and should be used only for that purpose.
In this case, you should use the second method.
Please correct me if I am wrong.
It is best to declare variables inside the constructor for the sake of consistency. A variable may require something like a loop or an if-else statement to initialize it, which can not be done in the declaration without placing the operation inside of a method.
The exception to this rule is static variables, which should be declared outside of the constructor.
Single-line declarations cannot contain complex initialization logic.
If you initialize a variable as:
class AnotherClass
{
MyClass anObject = new MyClass(); //MyClass() throws a checked exception.
}
then you'll find that you cannot provide the initial value in the single line. You'll need to place such code in a block, that quite obviously goes inside a constructor (or in a non-static initialization block):
Using a constructor:
class AnotherClass
{
MyClass anObject;
AnotherClass()
{
try{this.anObject = new MyClass();}catch(SomeException e){/*handle exception.*/}
}
}
Using a initialization block:
class AnotherClass
{
MyClass anObject;
{
try{this.anObject = new MyClass();}catch(SomeException e){/*handle exception.*/}
}
}
I find that the latter makes for less understandable code, as the declaration and initialization are separated from each other, and the initialization does not occur in a constructor coded by the developer (although there is no difference at runtime).
The same goes for other complex routines involved in initialization of fields. For example, if you intend to initialize an Array or a Collection and set the contents of the array/collection to some default value, then you should do so inside a constructor:
class AnotherClass
{
Integer[] integers;
AnotherClass()
{
this.integers = new Integer[10];
for(Integer integer: integers)
{
integer = Integer.MIN_VALUE;
}
}
}
Related
I'm developing a LALG compiler to my college course on Java 1.6. So I did a types class and grammar class.
EnumTypes
public enum EnumTypes {
A("OLA"),
B("MUNDO"),
C("HELLO"),
D("WORLD"),
/**
* The order below is reversed on purpose.
* Revert it and will you get a NULL list of types furder.
*/
I(EnumGrammar.THREE),
H(EnumGrammar.TWO),
F(EnumGrammar.ONE),
E(EnumGrammar.ZERO);
private String strValue;
private EnumGrammar enumGrammarValue;
private EnumTypes(String strValue) {
this.strValue = strValue;
}
private EnumTypes(EnumGrammar enumGrammarValue) {
this.enumGrammarValue = enumGrammarValue;
}
public String getStrValue() {
return strValue;
}
public EnumGrammar getEnumTiposValue() {
return enumGrammarValue;
}
}
EnumGrammar
public enum EnumGrammar {
ZERO(EnumTypes.A,EnumTypes.B,EnumTypes.F,EnumTypes.D),
ONE(EnumTypes.C),
TWO(EnumTypes.B,EnumTypes.H),
THREE(EnumTypes.D,EnumTypes.A,EnumTypes.C);
private EnumTypes[] values;
private EnumGrammar(EnumTypes ... values) {
this.values = values;
}
public EnumTypes[] getValues() {
return values;
}
}
When I call EnumTypes.E.getEnumTiposValue().getValues() where are supposed to be the EnumTypes.F value is NULL.
Main
public class Main {
public static void main(String[] args) {
//prints [A, B, null, D]
System.out.println(Arrays.toString(EnumTypes.E.getEnumTiposValue().getValues()));
}
}
There are a workaround or something like that?
Thanks!
Essentially, it is always a very risky thing to allow a reference to an object to get outside of the class before the class is fully constructed, that is before the constructor is finished. Enums are singletons. Here you have two classes whose constructors receive each other's instances in a circular dependency. Add to this that class loading is lazy, so the classes will be loaded and enum instances created as you go and it sounds quite reasonable that the ends result depends on the order in which the enums are initialized.
I can't quote the corresponding point from JLS right now (I'll look for it), but I believe that if you allow a reference to an object to "leave the class" from outside of the constructor (which happens here due to enums being singletons initialized by the JVM), the JVM is free to do something strange.
EDIT: these points from the JLS are of importance for the case:
17.5.2 - A read of a final field of an object within the thread that constructs that object is ordered with respect to the initialization of that field within the constructor by the usual happens-before rules. If the read occurs after the field is set in the constructor, it sees the value the final field is assigned, otherwise it sees the default value. Since enum values are internally treated like static final fields (see 16.5 below), if you reference one enum from inside the constructor of another enum whose constructor references the first one, at least one of these two objects will not yet have been fully initialized and so the reference may still be null at this point.
16.5 - The definite assignment/unassignment status of any construct within the class body of an enum constant is governed by the usual rules for classes
8.3.2 - rules for initialization of fields
12.4.1 - when initialization occurs
Here is what's happening, in order:
Your code calls EnumTypes.E.getEnumTiposValue(), triggering class loading of EnumTypes.
Static initialization of EnumTypes begins - its enum constants will be initialized in the order they're declared.
EnumTypes.A through EnumTypes.D are initialized.
EnumTypes.I begins initialization - its constructor call references EnumGrammar.THREE, triggering class loading of EnumGrammar.
Static initialization of EnumGrammar begins - its enum constants will be initialized in the order they're declared.
EnumGrammar.ZERO is initialized - its constructor call references EnumTypes.A, EnumTypes.B, EnumTypes.F, and EnumTypes.D. Out of those, EnumTypes.F has not yet been initialized. Therefore, the reference to it is null.
From there, static initialization of the two enum classes finishes, but it doesn't matter for EnumGrammar.ZERO - its values field has already been set.
For the workaround, suppose that you have EnumA and EnumB, I will just put EnumB's name in EnumA's constructor.
When you have to retrieve EnumB from EnumA, you can simply use EnumB.valueOf(EnumA.this.enumB)
For example, Question is the EnumB
public enum Question {
RICH_ENOUGH(R.string.question_rich_enough, Arrays.asList(Answer.RICH_ENOUGH_YES, Answer.RICH_ENOUGH_NO)),
ARE_YOU_SURE(R.string.question_are_you_sure, Arrays.asList(Answer.ARE_YOU_SURE_YES, Answer.ARE_YOU_SURE_NO)),
FOUND_A_NEW_JOB(R.string.question_found_new_job, Arrays.asList(Answer.FOUND_A_NEW_JOB_YES, Answer.FOUND_A_NEW_JOB_NO)),
// ...
and Answer is the EnumA
public enum Answer {
RICH_ENOUGH_YES(R.string.answer_yes, "ARE_YOU_SURE"),
RICH_ENOUGH_NO(R.string.answer_no, "THAT_SOMEBODY"),
ARE_YOU_SURE_YES(R.string.answer_yes, null),
ARE_YOU_SURE_NO(R.string.answer_no, "FOUND_A_NEW_JOB"),
FOUND_A_NEW_JOB_YES(R.string.answer_yes, "GO_FOR_NEW_JOB"),
// ...
private final int answerStringRes;
// Circular reference makes nulls
private final String nextQuestionName;
Answer(#StringRes int answerStringRes, String nexQuestionName) {
this.answerStringRes = answerStringRes;
this.nextQuestionName = nexQuestionName;
}
Whenever I need to get the next Question from an Answer
public Question getNextQuestion() {
if (nextQuestionName == null) {
return null;
}
return Question.valueOf(nextQuestionName);
}
This should be simple enough to be a workaround.
Example source: an open source Android app for fun I just written last night - Should I Resign?
I was wondering what the difference is between
public final type attribute_name;
and
private type attribute_name;
public type getA_name() {
return attribute_name;
}
Basically I want to make an attribute read-only, so it can't change after it has been initialized.
Do I make it public final, or do I make it private, and only make it accesible through a get method (without a set method)?
When it's not final but private, the class itself is able to change the value.
A final field MUST be set before the constructor exits. Once set, the reference cannot be modified (the value cannot be reassigned). Emphasis on the cannot be reassigned. This means that while the reference cannot change, the value itself can change.
This is legal:
final List<Integer> list = new List<Integer>();
list.add(5); // the value of list changes, but the reference doesn't
This is not:
final List<Integer> list = new List<Integer>();
list = new List<Integer>(); // may seem sort of redundant but the compiler won't allow it nonetheless
A private variable with a only getter can be reassigned internally by the class that holds it (but it's not visible externally so it cannot be reassigned outside the class holding it). Also, outside the class the reference is inaccessible so the variable cannot be modified except by the class holding it.
A final variable cannot be reassigned anywhere, but if it's public, another class can still access the reference and change the value of whatever object it points to.
If you don't want the variable to be reassigned after initialization as you described, use both final and private.
Use final for something like this:
public class User {
private final long registrationTimeMillis;
public User(/* various parameters probably would be here */) {
registrationTimeMillis = System.currentTimeMillis();
}
public long getRegistrationTimeMillis() {
return registrationTimeMillis;
}
}
We don't expect that a user's registration time will change, so it makes sense to not allow it to change after construction.
Use private with no setter for something like this:
public class VendingController() {
private int drinksStocked = 0;
private int drinksDispensed = 0;
public void dispenseDrink() {
drinksDispensed++;
}
public void stockDrinks(int numberOfDrinks) {
drinksStocked = getDrinksRemaining() + numberOfDrinks;
drinksDispensed = 0;
}
public int getDrinksRemaining() {
return drinksStocked - drinksDispensed;
}
}
We don't want the value of drinksDispensed to change except when dispenseDrink() or stockDrinks(int numberOfDrinks) is called. It still needs to be able to be reassigned by it's own class when the vending machine is refilled though, so we shouldn't make it final
With respect to using public final, generally in Java that's only done for constants and that static keyword is also included since constants shouldn't be dependent on an instance.
An example of when it makes sense to use public static final
public class UnitConversions {
public static final double CENTIMETERS_PER_INCH = 2.54;
}
It could then be used in a method as follows
public double convertFromCentimetersToInches(double centimeters) {
return centimeters / UnitConversions.CENTIMETERS_PER_INCH;
}
Best of luck OP and happy coding.
More reading on final fields
This depends on some factors.
If this is a real constant that is known before and will never change, then use final. In Java final fields can be initialized in the constructor as well, so if your value is known at construction time then you can use final too.
If this value gets set (once, multiple times) during runtime then use private + getter.
The final modifier allows a field to be assigned only once - it cannot be changed after that and it has to be set at during object construction (that is, before the constructor returns).
If you want to make the field read-only, use the principles of information hiding: make it private and provide a public getter that returns the field (or a copy of it for non-primitive types).
You should use public final only for true constants. Even if your field is immutable because of final it is often a good idea to still make it private.
The correct way is to think in the future. What would help you achieve your goals? Maybe later you would also like to give that variable a value. If I were you, I'd do this by creatin a get method and keeping the variable private.
Full documentation for final keyword : http://en.wikipedia.org/wiki/Final_(Java)
Depends on where you want to access it from. Public variables can be accessed from any class within the project and package where private can only be accessed from the class where the variable is.
The 'final' operator makes it permanent and read-only.
Let's assume that type is a reference to an object, not a primitive type.
public final type attribute_name means that attribute_name cannot be reassigned to refer to something else. But attribute_name can be used to call a method that changes its state.
In private type attribute_name, only methods within the class can call methods on attribute_name.
So if you want it to remain constant, use approach (2). Limit the public methods to ones that ultimately call methods on attribute_name that don't modify its state.
I have noticed a thing that a constructor and a simple method of a class do the same work. what is the exact reason to create a construct of a class? If i create MyClass(){} constructor and MyClassMethod(){} method it will do the same work as I write the body part of those method and constructor. So what is the need of construct? Does it have any special use ?
A constructor and a method are two different things. The fact that you can write the same or similar code inside them is irrelevant.
When a new object is created a constructor is called. If you don't specify one the compiler will create a default one for you. This is the place where initializaton of the object's fields takes place and memory is allocated for the object. This is a concept that all object-oriented languages have. A new object must be initialized somehow. Memory needs to be allocated. In Java you don't manage the memory yourself (at least not directly anyway) so this is the purpose of the constructor. Note that since a constructor is always executed, this behaviour is enforced as soon as you call e.g. Person p = new Person();.
Now since a constructor is always being called, you have an option here: do you let the default constructor execute or do you create one yourself? Perhaps there are fields that need to be initialized in a way other than their default values. Or perhaps you need to not allow creating an object without providing some values. If you define a constructor yourself, the compiler does not create a default one for you. So if I have public Person(String firstName, String lastName) {} then I have created a specific rule that is again enforced by the system: a new object of class Person cannot be created unless you give a first name and last name:
Person p = new Person(); // this would give a compile error
Person p = new Person("John", "Smith"); // this is the only way to create an object now
Using a method you cannot enforce this. The programmer using your class might call your method or not. The constructor is a part of the lifecycle of the object. Methods define the behaviour of the object
Some points :
1) Constructors are the only way to set final instance variables .
public class SomeType {
final int x ;
SomeType(int y){
x=y;
}
}
2) A class with private constructor cannot be sub classed.
3) If your class is a subclass and the base class doesn't have a default constructor , then you need a constructor in your class to call the super class constructor.
One of the benefits of using a constructor over a method is that you can be assured the constructor was called and the work within the constructor was performed.
The language specifies that to construct an object a constructor must be called. So if you use a custom method to establish the initial state of your object, you will need to call the default constructor first. Why make two method calls when you can perform the work in one call the constructor and be assured the object has been properly initialized?
public class Test(){
private Integer x;
public Test(){
}
public Test(Integer x){
this.x = x;
}
public void setX(Integer x){
this.x = x;
}
public void doSomethingWithX(){
this.x.toString();
}
}
Test test = new Test(8);
test.doSomethingWithX(); //I know x has been declared and assigned
Test test = new Test();
test.doSomethingWithX(); //X has not been assigned results in NPE
If you create a new Object of MyClass it will automatically call the constructor - you can initialize all members within it, and be sure that this object´s members are all initialized.
Generally:
A constructor is always called once when you create a new Object of this class, and you can´t call it manually.
And don´t do "real" work in a constructor, as it will slow down the creation of objects of this class - only initialize your class/members there.
You can also use different constructors, depending on your needs - but if you create a constructor, there is no more default constructor!
Example:
public MyClass {
int score;
public MyClass(int sc) { // already know the score
score = sc;
}
public MyClass() { // don´t know the score yet
score = 1;
}
public void addScore() {
score += 5; // i know for sure that score is not zero
}
}
Essentially a constructor is just a special method that implicitly returns an object of its containing type. You should generally use constructors for creating objects - this is what people expect to see.
However, there is a useful idiom called the factory method (more info at this link) which is essentially using a static method to construct an object, the key advantages being
You can give a factory method a more descriptive name (whereas of course a standard constructor has to be named after the containing class).
They don't have to return an object, giving more flexibility.
They can return a sub-types of the class.
You can set final fields without initializer in a constructor. This helps to build immutable instances:
class Number extends Expr {
private final int n;
public Number(int n) {
this.n = n;
}
public int getValue() {
return this.n;
}
}
So after a constructor like this, you can rely on the fact that the instance is initialized completely (and in this case, it's values are immutable/constant).
Constructor is not like simple methods. It is called every time when the object of that particular class is created. You don't need to call it explicitly.
There are somethings that we need to do immediately when the object is created, for instance when you create a GUI kind of thing you want to set many properties on the time of creation like size of window etc.
Another benefit of constructor is security of class. You cannot create a object unless you know the right perimeters of constructor.
More details:http://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
A constructor is a special method of a class or structure in object-oriented programming that initializes an object of that type.
Some points :
1. A constructor eliminates placing the default values.
2. A constructor eliminates calling the normal method implicitly.
These are the benefits of constructors.
Automatic initialization of objects at the time of their declaration.
Multiple ways to initialize objects according to the number of
arguments passes while declaration.
The objects of child class can be initialised by the constructors of base class.
Java beginner here who is terribly confused as to why
1) this is valid:
public class MyArrayOfObjects {
MyArrayOfObjects[] myArray = new MyArrayOfObjects[5];
void InstantiateElements (){
myArray[0] = new MyArrayOfObjects();
}
}
2) while this is not:
public class MyArrayOfObjects {
MyArrayOfObjects[] myArray = new MyArrayOfObjects[5];
myArray[0] = new MyArrayOfObjects();
}
from my understanding, each element of the array of objects is instantiating a MyArrayOfObjects object. So why does option 1 work while 2 does not?
myArray[0] = new MyArrayOfObjects(); is a statement – a line of executable code.
Statements can only appear in methods or initializer blocks.
Class definitions can only contain declarations (fields, methods, constructors, inner classes), not statements.
Fields can also have initializers.
Statements other than variable declarations must occur in:
Methods
Constructors
Initializer blocks
In your second block of code, the statement assigning a value to the first element of the array is not a variable declaration, so it can't occur directly in the class.
As for why Java is designed this way - to my mind it just makes things simpler. You should put logic to be executed as part of initialization into a constructor. (I would generally try to avoid initializer blocks as well, as it's easy to forget about them when debugging.)
From section 8.1.6 of the Java Language Specification:
A class body may contain declarations of members of the class, that is, fields (§8.3), classes (§8.5), interfaces (§8.5) and methods (§8.4). A class body may also contain instance initializers (§8.6), static initializers (§8.7), and declarations of constructors (§8.8) for the class.
You have to put this line:
myArray[0] = new MyArrayOfObjects();
into an constructor. The class body can't contain statements, just declarations.
Not exactly an answer to why, this has been answered already but as an addition. You could initialize your array on declaration with an array initializer:
public class MyArrayOfObjects {
MyArrayOfObjects[] foo = new MyArrayOfObjects[] { new MyArrayOfObjects(), null, null, null, null };
}
I am having some trouble understanding classes in Java.
Such as how do you declare "Inputter" in the helper class like this?
public class Helper
{
public void Helper(String z)
{
if(z.length() == 0)
{
System.out.println("You can't leave it blank!");
System.exit(1);
System.out.println("It's not working... ;(");
}
}
public void Inputter(int a)
{
// blah blah
}
}
Would you call it like this?
Helper x = new Inputter();
Please help, and NO this is NOT a homework question.
Thanks,
Smiling
EDIT: Would this be right:
public class Helper
{
public Helper(String z)
{
if(z.length() == 0)
{
System.out.println("You can't leave it blank!");
System.exit(1);
System.out.println("It's not working... ;(");
}
}
public void Inputter(int a)
{
// blah blah
}
}
and declared with:
Helper x = Helper();
And thanks everyone for giving me a warm welcome to StackOverflow! :D
Your problem is not with classes, it is with constructors and methods, and the difference between them.
Methods can have any name you like, they must declare a return type (possibly void), and they're called like this:
ReturnType r = methodName(param1, param2)
Constructors are used to create instances of classes (objects). They must have the same name as the class, they must not have a return type (not even void), and they're called like this:
MyClass m = new MyClass(param1, param2);
There are several problems in your code:
Helper has the correct name for a constructor, but because it declares a void return type, the compiler will treat it as a method.
Inputter doesn't even have the correct name for a constructor. To use it as a constructor with new, it would have to be part of a class called Inputter
Perhaps you should start out reading the introduction to OO part of the Java tutorial.
Inputter() that you have defined is a method or you can call it a behavior. You cannot create an instance for a behavior.
One more problem is that you cannot have return types on a constructor. Helper is the class name and the constructor is having a return type which is incorrect
Regarding your quesiton, if you want to call Inputter, you should do it something like the following.
Helper helper = new Helper("test");
helper.Inputter(100);
It is a good practice to start methods with smaller case letters.
The only object here is Helper. If you want to make a new helper, then you will instantiate it by saying
Helper X = new Helper("blah blah");
If you want to call Inputter then you just say
X.Inputter(1234);
Which will call the Inputter function for the specific instance X of Helper
You must create an instance of Helper Before you can use Inputter:
Helper x = new Helper("some string");
to use Inputter, try this:
//create a new helper
Helper x = new Helper("some string");
//use the Inputter method of the helper.
x.Inputter(1);
The thing to understand here is that Helper is the class, x is an instance of a class, and Inputter is a instance method (which is different from a static method) in the Helper class.
Inputter in your code is not a class. It is a method.
To make following statement correct:
Helper x = new Inputter();
you would need to create Inputter class that extends Helper class.
Inputter is not a class. It's a method of the Helper class. So you cannot instantiate it.
You can call it like this
String someString = "some string";
Helper x = new Helper(someString);
int someInt = 1;
x.Inputter(someInt);
The new keyword is reserved for instantiating (fancy word for saying "making new") classes. The way your class is made, when you make a new Helper, a function is run. That is the construct function, and is named like the class.
Once you instantiate a class, you gain access to the goodies within it (exception is a static method/attribute, where anyone can access it); all within the class that isn't private or protected.
Now, a short intro on OOP (Object Oriented Programming):
You have classes, which are basically blocks of functionality. Within these classes are two things: Methods and Attributes (many names for that, but that's what I call them.)
A Method is basically a good ol` function: It has an input and an output.
An attribute is really like any other variable.
Now, in Java and many other OO languages, there's a separation between the class declaration and class instances. A class declaration is basically the static coded class; exactly what you put in the code. A class instance is taking the class declaration and putting it into use: You can change and use the methods and attributes inside them.
So, if you want to call Inputter, you should do it like this:
Helper bob = new Helper('Bloop');
bob.Inputter(42);
What happened here? We made a new variable called bob which has a type of Helper. When constructing the new Helper, we also run the constructor. Looking at the constructor function, we pass a value to it (in this case, 'Bloop'), and the function is run normally, without us having to manually call it.
Now we want to use the Helper class' Inputter method. For that, we need to access an instance of the Helper class (in our case bob), by using bob. (notice the dot), and then calling it like any other function: Inputter(parameters). Gluing it together we get bob.Inputter(parameters)
This was a really rather lame explanation of Object orientation that didn't cover that much, but it should get you started. I recommend getting a book about Java or reading online tutorials.
First, start with the basics.
Classes best represent nouns. That means a Class is a model of (typically) a thing. Methods best represent verbs on those nouns. Drifting away from this ideal is sometimes necessary; however, the further you stay away from such an ideal, the harder it will be to understand what is going on. With a nod to the exceptions, since you're a beginner let us not get wrapped up in the exception but follow the rule.
public class Person {
private String name;
private int age;
public Person(String name) {
this.name = name;
this.age = -1;
}
public void setAge(int value) {
if (value < 0) {
throw new IllegalArgumentException("Age must be greater than zero");
}
this.age = value;
}
public int getAge() throws IllegalStateException {
if (age < 0) {
throw new IllegalStateException("Age was not set");
}
return this.age;
}
}
Read through the class above, and use its style for your beginning programs. When you find that its style is hindering you more than helping you, then you might have found a place where other techniques are needed.