I am trying to learn Java by my self and i am making a game you all properly know, which is Monopoly.
I have searched for my answer but couldnt find it, so here it is.
I have a class Field with two variables fieldnumber and fieldname. My idea is to make a field with a number, so the program know where the players are (not relevant now).
The fieldname and fieldnumbershould only be readable (means not editable) after the program have created the fields and names for the fields.
I need to know how i can intialize these two variables into a contructor and make the variables to be only "getters", so they cant be changed later on.
(obs: the class Field is only a subclass, i need to use the data in the main class later on)
Im a bit confused and tried to read the book i am using, but no luck.
Declare the fields final, assign them in constructor and do not write setters.
Should the number of properties increase, you may consider using builder pattern to avoid constructor with many arguments.
class Field {
private final int fieldNumber;
private final String fieldName;
public Field(final int fieldNumber, final String fieldName) {
// you may validate the values here and throw exception in case of non-valid values
this.fieldNumber = fieldNumber;
this.fieldName = fieldName;
}
public int getFieldNumber() {
return fieldNumber;
}
public String getFieldName() {
return fieldName;
}
}
I suggest to make the two attribut as private (not accessible), initialize them when creating the instance, and you can use the getter to get their values:
class Field{
private String fieldname;
private int fieldnumber;
public Field (String fieldname, int fieldnumber)
{
this.fieldname = fieldname;
this.fieldnumber= fieldnumber;
}
public String getFieldname(){
return fieldname;
}
public int getFieldnumber(){
return fieldnumber;
}
public String toString(){
return fieldnumber+ " " +fieldname;
}
public boolean equals(Object obj){
Field field = (Field) obj;
return (fieldnumber == field.fieldnumber && fieldname.equals(field.fieldname);
}
}
A "getter" is a method that returns the value of your field.
A "setter" is a method typically taking one argument, setting the value of your field (possibly after some validation).
For good encapsulation, your instance fields should typically only be accessed within the maximum scope allowed within context (typically private fields with getters/setters, sometimes protected or package-protected fields when inheritance or more complex settings are required)
A field marked with the final non-access modifier can only be assigned once
In your case, if the fields are scoped within the instance of your class, but will never change once assigned, you can mark them final and assign them in a constructor or instance statement (no setters).
If they are not bound to an instance, but rather to the class, then you can mark them constant (static final) and assign them right away (you can then safely make them public if they are immutable - i.e. Strings or primitives)
Getter means a method that returns a value an object stores. A variable being a getter doesn't mean anything. Getters are usually used to get variables that are declared private; that is, variables that are not 'visible' from outside the class. See the example:
class Example {
private int value;
public Example(int valueToBeSet) {
this.value = valueToBeSet;
}
}
In the above example, the variable value is only visible from the class Example; any other class cannot get that variable. This is useful when you want that no other class is able to change its value. However, to get the value from the object, you use a getter:
class Example {
private int value;
public Example(int valueToBeSet) {
this.value = valueToBeSet;
}
public int getValue() {
return this.value;
}
}
Here the method getValue() is a getter. You cannot change the value, because it is private, but you can call the method getValue(), and get the value, because the method is public.
Other way to assign a variable's value, be able to get its value, but not be able to change it, is to use the final keyword:
class Example {
public final int value;
public Example(int valueToBeSet) {
this.value = valueToBeSet;
}
}
This way the variable's value can only be set once, in the constructor, and never again. However, you can still get the value from outside the class because it is public. This is often a good way to do things, however it has its downsides; namely as I explained, you cannot change the value anymore, and to get an object with a different value, you would have to create a new object altogether. This is the closest you can get to a "getter variable".
Related
I am trying the Jacco testing and I am able to test the getStudentId from a class called Student which has:
public String getStudentId() {
return studentId;
}
When I try to test my other class named Product, I get an error - the only difference between the two is in the getX method. The getName method of Product is:
public String getName() {
return this.name;
}
and the error message says:
constructor Product in class Product cannot be applied to given types
The keyword this references the instance of the object you are currently in. Imagine having a class like this:
public class A {
private String property;
public void changeProperty(String property) {
this.property = property
}
}
Outside of the method the variable name property is not ambiguous and references the member variable of class A. But it is ambiguous inside the method changeProperty because there is also the argument named property.
How does Java resolves this conflict? If you just type property you will always reference the object with a smaller scope, so the argument of the method and not the member variable. By using this.property you can reference the member variable again.
If there is no such conflict in your object, like in your example, then you do not need the this statement and this.name is the same as name.
However as prevention of very nasty bugs one could always use this when referencing a member variable, just as good practice. Imagine you would create a method with such a name conflict in the future and forget about the member variable, whoops you easily create a bug that is hard to debug.
Some programmers even go further and do always give member variables other names than arguments, to prevent such name conflicts. For example member variables are often named:
mProperty or
_property
Note that the method this(...) references a constructor of the own object. It can be used in a constructor to pass the task to another constructor like:
public class A {
public A(String fileName) {
this(new File(fileName), true);
}
public A(File file) {
this(file, true);
}
public A(File file, boolean doSomething) {
// Code ...
}
}
Analogously there is also the keyword super which references the parent-class. For example:
public class A {
protected String property;
}
public class B extends A {
private String property;
public void foo() {
// Property of B
System.out.println(property);
// The same
System.out.println(this.property);
// Property of A
System.out.println(super.property);
}
}
This keyword can also be used to reference parent-constructor or other methods of the parent class.
So all in all it is just about resolving such name conflicts.
Now we know that, it is easy to see that the code you posted does not contain the bug.
When you use this.name you are using a attribute defined in your class, the attribute name. However, when you use only name, it could be any variable called so in your code, even the attribute. Example:
public String getName(){
String name = "Mery";
this.name = "Jacob";
return name;
}
This method return the value "Mery". If you put return this.name then you return the value "Jacob".
There's a chance you set studentID to a public variable. Anytime you are using this.whatever to return a variable from a getX function, the this. implies it's a private variable. More likely than not the studentID is public and that's why you got away with no 'this.' in front of it.
In Java if we declare primitive variable (not local) like int, float etc and do not initialize them, then they get initialized by their default values. Can we achieve something like this for reference variables? For example if I have an employee class which contains two int variables and in another class if I have created only reference of the employee class so is it possible that int variables get initialized by zero?
In Java if we declare primitive variable (not local) like int, float etc and do not initialize them, then they get initialized by their default values.
No, they don't. Fields do, both instance fields and class fields, but not variables.
Can we achieve something like this for reference variables?
Reference fields get the same behavior. The value they're initialized with is null.
For example if I have an employee class which contains two int variables and in another class if I have created only reference of the employee class so is it possible that int variables get initialized by zero?
If by "created a reference" you mean you've created an Employee instance, then any fields in that instance will be initialized to their defaults unless the Employee constructor gives them a different value.
Fields are initialized to null if they are from some "type" (other than primitive types), anyway if you provide default values in your "default" constructor for that class in particular you can override the default null values for those.
final class Employee {
private String firstName;
private String lastName;
// You can have more constructors here
public Employee() {
firstName = "Default Value for First Name";
lastName = "Default Value for Last Name";
}
// Getters, Setters
}
Only not local fields are initialized to default values when not explicitly initialized. So, something like this
public class Main {
boolean flag;
void foo(){
System.out.println(flag);
}
}
compiles and foo() method would print false, while something like this
public class Main2 {
void foo(){
boolean flag;
System.out.println(flag);
}
}
wouldn't even compile. Furthermore, default value for a reference is null.
What you can do is designing your class in such a way that, when class is initialized, a value is assigne to its instance variables, something like
public class Main {
boolean flag;
{
flag=true;
}
void foo(){
System.out.println(flag);
}
}
I'm a bit confused about the use of getter/setters and constructors (see the below code for an example)
public class ExampleClass {
private int value = 0;
public ExampleClass () {
value = 0;
}
public ExampleClass (int i) {
this.value = i;
}
public int getValue() {
return value;
}
public void setValue(int val) {
this.value = val;
}
public static void main(String[] args) {
ExampleClass example = new ExampleClass (20);
example.setValue(20);
//Both lines above do same thing - why use constructor?
System.out.println(example.getvalue());
}
}
All I've learned is that we need getters/setters for security and that they can also be used to change or edit values later on.
My question is that if the constructor is the point of initialization and a default constructor is always present, why use a constructor with parameters to initialize values instead of getters/setters?. Wouldn't using the getter and setter provide security as well being able to easily change values at any stage. Please clarify this point for me.
default constructor is always there
Well actually its not always there. A default constructor is the one which is provided by the compiler (of course it is a no-arg constructor ) Only if there is no other constructor defined in the class
why we use constructor with parameters to initialize values instead of set get
Because there could be a condition that an object can always be created only when all the values are provided at the time of initialization itself and there is no default value. So all values must be provided otherwise code will not compile.
Consider this Book class
public class Book {
private String title;
private String author;
public Book(String title, String author){
this.title = title;
this.author = author;
}
//getters and setters here
}
Consider a condition where a book can be created only if it has title and author.
You cannot do new Book() because no-arg constructor is absent and compiler will not provide one because one constructor is already defined.
Also you cannot do new Book() because our condition does not meet as every book requires a title and author.
This is the condition where parameterized constructor is useful.
Sometimes, when creating a new object of a class, some values HAVE TO be provided. For an example, when connecting to database and creating Connection class object you have to provide a connection string, so that it knows what are you connecting to. Creating new connection without specyfing target database would be pretty useless, right?
Also, take a look at this
Foo foo=new Foo(1,2,3,4,5,6,7);
and this
Foo foo=new Foo();
foo.setP1(1);
foo.setP2(2);
foo.setP3(3);
foo.setP4(4);
foo.setP5(5);
foo.setP6(6);
foo.setP7(7);
First one looks better, right?
My question is that if constructor is point of initialization and
default constructor is always there so why we use constructor with
parameters to initialize values instead of set get.
If you think about an object transitioning into different states then it makes sense to have a parameterized constructor alongwith setters and getters. Let me try to put a real life scenario: Think about an Employee class, a new employee joins, you don't know many details but few and you create the object of Employee with defualt and base value of its attributes. You need to register the employee in the system and hence you used the parameterized constructor. Once you get more details about the employee, you use getters and setters to update the attributes.
this is purely upto your coding style. But IMO, I would use parametrized constructor:
to initialize those values which should not be changed. (like username parameter for a person object)
to initialize those values, without setting which, the object will be in invalid state.
Say, you are sending login parameters to a method. You can use in these to ways
Login obj = new Login();
obj.setUsername("user");
obj.setPassword("pw")// what if someone commented this out, or you forget to call it
and otherway,
Login obj = new Login("user", "pw");
while you can send Login object just after setting username in 1st case, it would be invalid at recieving end. but the second method is less prone to bugs, bcz it becomes necessary to pass all the required parameters.
Just to make it easier. It takes less code to use a constructor than to create an object and use the setters.
Sometimes you don't need to set all the fields to specific values at the time of creating. For examle, when you make an array. Also, as already said, it's safer when you use getters -- you can't get nullpointer.
Remember to write the default constructor when you've defined constructor with parameters. Or be sure not to use it.
First, both methods: Constructor and Setter are safe ways to change object's attributes. Are expected from Class author to expose or not safe ways to modify an instance.
The default constructor is always provided if you have not written one:
// Example of a Class with a Default Constructor
public class GetSet {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public static void main(String[] args) {
// Theres a implicit Default Constructor here
// Its ok to do that
// GetSet obj = new GetSet();
GetSet obj = new GetSet();
}
}
// Example of a Class without a Default Constructor
public class GetSet2 {
public GetSet2(String value) {
this.value = value;
}
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public static void main(String[] args) {
// GetSet2 obj = new GetSet2(); // compile time error
// Default constructor is not provided, since u wrote one
}
}
2. About which is better: Using a constructor or via setter, it depends on what u want. If you will only modify an attribute of a existing object, u may use the setter, or for a completely filled object you may prefer the constructor instead.
// Example of modifing an obj via Setter and Constructor
public class GetSet3 {
public GetSet3(String value1, String value2, String value3, String value4) {
this.value1 = value1;
this.value2 = value2;
this.value3 = value3;
this.value4 = value4;
}
private String value1;
private String value2;
private String value3;
private String value4;
// ... Getters and Setters
public static void main(String[] args) {
// Its easier to this
GetSet3 obj;
obj= new GetSet3("j", "a", "v", "a");
// instead that
// its also easy to forget or do something wrong
// when u have a lot of attributes to set
obj.setValue1("j");
obj.setValue2("a");
obj.setValue3("v");
obj.setValue4("a");
}
}
It's easier and safer to initialize your object variables via your constructor to avoid nullpointers.
If you instantiate your object without initializing your variables first and you do a get operation on one of your null variables, you might get a nullpointer exception at runtime because you forgot to manually set its value.
On the flipside of that, if you always initialize your object variables in your default constructor, you have a seriously reduced risk of getting nullpointer exceptions during runtime because none of your variables can be null unless you specifically set them via a setter (which is not recommended).
Constructor with arguments makes you get the object fully constructed. If you want to use default one, you will have to make sure the fields are set using setters. During set of some property, assume the exception is thrown, now you have an object which is not usable. In several cases, setter wouldn't be exposed but getters. In those cases, having constructor with arguments or a named constructor is the right option. In a nutshell, getters and setters do have their own importance rather than initializing the object.
Why use getters and setters?
Because you write it using less, more elegant and better readable code when you set the values as parameters in a constructor. Moreover, sometimes some fields are indispensable for the object, so a parameter constructor prevents the user from creating an object omitting necessary fields for the object's functionality. One is though not "oblidged" to call the setters.
To answer this question, I say by writing getters/setters, we create a provision to add any validation method in the future, currently, there is no validation, but if anything goes wrong in the future we just add validation logic in the setter.
we can also write the logic/validation in constructors but it's not a good practice. The constructor should be used only to initialize your object's state/fields. You should delegate the responsibility of other things to other methods.
Note that a constructor is called only once i.e, whenever you create a new object With a sufficiently large input, you can cause an exception in your constructor.
This is one of several reasons why you should not use a constructor to contain "business logic".
To actually understand the meaning of encapsulation, example that class private fields must be accessed through class public methods is as per definition, but actually stll it doesn't make difference as the field is still accessible as it is.
So,I think there should be some processing inside getters/setters to hide how the field is being handled. But it breaks the principal of behind pojos. How can one handle this situation?
I'm not sure what according to you is "the principle of POJOs". The following is a POJO and still hides implementation details behind getters and setters:
public class Example {
private int thousands;
private int units;
public void setValue(int value) {
thousands = value / 1000;
units = value % 1000;
}
public int getValue() {
return 1000 * thousands + units;
}
}
Encapsulation means not to expose the internals of your class.
In the Java context it means that the attributes of your class should NOT be accessible by other classes, instead your class should provide methods that will allow to access the attributes. In cases of POJO classes these methods will only allow to set (setters) and get (getters) the values of the attributes from the POJO class.
The goal of encapsulation is to protect the attributes of your class from being modified by other classes. Your class is obviously able to do whatever you want with the attributes inside your classes.
No, the field is not accessible as it is. All it takes to make a method a getter or a setter ist the proper signature.
public String getFoo() {
return null;
}
This is a perfect getter for a String foo, even though it returns null.
public void setFoo(String foo) {
// do nothing
}
This is a perfect setter for the same member, even though it does nothing.
One of the many uses of getters and setters is to restrict the value of the variable. By making the data members private and keeping the getters and setters public, the programmer can keep a check on the value of the variable. For ex:
class Employee
{
private int age;
public int getAge()
{
return this.age;
}
public void setAge(int age)
{
if(age<18 || age>60)
this.age = age;
else
System.out.println("The age of the employee should be between 18 and 60");
}
}
In this case the age of the Employee can never be more less than 18 and more than 60.
Don't know why people usually mix Data Encapsulation with Data hiding. Data encapsulation simply means grouping data together whereas data hiding is a way to store this data so others cannot know it's internal implementation.
Lets say you have a class PersonalInfo in which you have fields like name,gender,age etc. As a programmer(which you are) you will provide user some way to enter these fields, save them in your PersonalInfo object using setter methods.IF user wish to see the information you simple call getters and display information. Your implementation as in you may store this variables in a map may varry. So you can say
public void setName(String name){
SomeMap.add("name",name);
}
Note *you are the programmer and you will always know the implementatio*n. Keeping the fields private is to allow only your class methods to access your data.
Imagine it this way. User can create an object. He may set all fields using getters and setters. It may be your implementation to calculate age using DOB(Date of Birth) in which case you will not provide setter for age. In this case user cannot say myObj.age=23. This is purely your implementation.Hope this clears the confusion!
It's still accessible but you see when you use it directly (public variable) you can change the value of variable without any restriction. The advantage of using such kind of private variables with setter and getter methods is that you can write code inside the setter method to check whether the value set is in the expected range or not. Or you can even store the value in different form than the apparent view. For example you may store the value of a variable by adding offset to the value of the parameter of the setter method and in getter method you may just revert back the process(Encapsulation). When the value set is not in the expected range you may even throw exceptions.
Example1:
Here var1 is a private variable
public void setValue(int var1){
if(var1<0){
//throw exception
}
this.var1=var1;
}
Example2:
public void setValue(int var1){
this.var1=calculatesomething+var1;
}
public int getValue(){
return calculatesomething+this.var1;
}
That's the use of encapsulation.....all the best
Encapsulation is to restrict the access to the Class's variables and to regularize the way of editing them.
Class Test
{
public int a;
public Test()
{
a = 0;
}
public getA()
{
return a;
}
public setA(int a)
{
this.a = a
}
}
Class TestMain
{
main()
{
Test t = new Test();
System.out.println(t.a); // This prints 0;
int a = t.getA();
a = 10;
System.out.println(t.a); // This still prints 0;
t.a = 20;
System.out.println(t.a); // This prints 20;
}
}
In the above example the programmer may not be intentionally changing the value of t.a but the value changes.
If he really intents to change it, then he should use the setter.
Encapsulation is the feature that java provides which solves certain practical problems and helps in extensibility.
If the Test and TestMain classes are written by same person, there wont't be any confusion.
But practically that is not the case.
Enum constructors must be either private or package default, and protected or public access modifier is not allowed. Why so
Because an enum, by definition, has a fixed set of instances which are declared and constructed in the enum itself. Using the constructor from outside of the enum class itself thus doesn't make sense.
And AFAIK, an enum constructor is always, explicitely or implicitely, private.
From the Java tutorial:
The constructor for an enum type must be package-private or private access. It automatically creates the constants that are defined at the beginning of the enum body. You cannot invoke an enum constructor yourself.
It doesn't make sense to be able to create new instances of an enum, so the language prevents you from doing so!
Enum is not meant to be instantiated (by you).
http://docs.oracle.com/javase/tutorial/reflect/special/enumTrouble.html :
Tip: It is a compile-time error to attempt to explicitly instantiate an enum because that would prevent the defined enum
constants from being unique. This restriction is also enforced in
reflective code. Code which attempts to instantiate classes using
their default constructors should invoke Class.isEnum() first to
determine if the class is an enum.
The reason you can't dynamically extend an enum is that the instantiated values are compiled into the bytecode for the Class object:
public T[] getEnumConstants()
Returns the elements of this enum class or null if this Class object does not
represent an enum type.
As a result, any attempt to construct a new instance would not be able to passed onto the actual Class, since Class objects cannot be changed. If you want this behavior, you'll have to simulate it yourself, and give it some kind of unique value to represent each one, then have an ordinal counter, and finally a static map (or some other structure) to hold all the values.
public class MyEnum {
private static AtomicInteger nextOrdinal = new AtomicInteger(0);
private static Map<Integer, MyEnum> instances =
new HashMap<Integer, MyEnum>();
private int ordinal;
private String name;
public MyEnum(String name) {
super();
this.ordinal = nextOrdinal.incrementAndGet();
this.name = name;
instances.put(Integer.valueOf(this.ordinal), this);
}
public String name() {
return name;
}
public int ordinal() {
return ordinal;
}
public static Set<MyEnum> getEnumConstants() {
return Collections.unmodifiableSet(instances.values());
}
public static MyEnum fromInt(int ordinal) {
return instances.get(Integer.valueOf(ordinal));
}
public static MyEnum fromString(String name) {
for (MyEnum val : instances.values()) {
if (val.name().equals(name)) {
return val;
}
}
return null;
}
}
You'll probably also want a .equals and .hashcode method, as well as preventing the same name from being used more than once (which you could do in the constructor and throw an IllegalStateException or something if you have a duplicate name).