convert mutable variable to immutable in java with less pain - java

sometime i have no choice to use mutable variable instead of immutable variables i know how many ways can create immutable vars but i wonder this way also correct its really convert mutable to immutable and i dont use concurrency or multithreading in my code just Curious?
public class Config implements FindIt {
....
private final class DateHolder{
private final Date dateContainDateObject;
DateHolder(String date) throws ParseException {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
dateContainDateObject = dateFormat.parse(date);
}
public Date getDate(){
return dateContainDateObject;
}
}
}
this is nested class and i use it like
private DateHolder holder;
and fill the holder variable in Config constructor class so holder variable are ThreadSafe ?

Date is a mutable object. Making it final means you can't change the reference to it, but you can still change what's at the reference (java.util.Date/Calendar nastiness strikes again, switch to the Java 8/Joda Time way if you can).
Don't expose any references to the Date member to the outside world. Instead make a defensive copy and pass that back instead. You might consider saving the time value as a final long instance member and only instantiating a Date when you need it.

can say is safe when you make class private and non-static, when you create form Config class you have only one DateHolder .
http://www.javapractices.com/topic/TopicAction.do?Id=29
why is static inner class singleton thread safe
http://www.javatpoint.com/how-to-create-immutable-class

Related

Why can private members in Java be modified from another class?

In the following example, x can be changed by class B even though it's a private member of class A. What's the reason for this?
import java.util.Date;
class A {
private Date x;
public A(){
super();
x = new Date();
}
public Date getDate(){
return x;
}
public void print(){
System.out.println(this.x);
}
}
class B {
public static void main(String[] args){
A a = new A();
a.print();
Date d = a.getDate();
d.setMonth(12);
System.out.println(d);
a.print();
}
}
The output is:
Initial date generated by A
Date changed by B
Date changed by B (why does it change a private member here?)
private prevents a variable from being accessed directly by another class. You cannot write d.x to read or write to x.
If the class chooses to return a reference to x via a public method, though, that's it's own choice to pierce the veil of privacy. Nothing stops A from allowing x to be read from a getter or modified from a setter.
In recent years the Java community has recognized the problem with this: namely, if you return a reference to a private mutable object, you open the door for your class's internal state to be mucked with without its knowledge. To protect against this, it has become good practice to make classes immutable whenever possible.
Indeed, Date is a perfect example of a poorly-designed mutable class. The java.time package introduced in Java 8 added a slew of immutable time and date classes to replace Date. You can now return a private Instant and not worry about callers being able to change it.
It's important to point out that immutability comes from how a class is defined. It's not a language-level feature like private. Confusingly, final can be used to make variables immutable, but applying it to a class does not make the class immutable (it makes it unextendable).
You're not changing the private property. Try this and see it fail:
A a = new A();
a.x = someOtherValue;
But the A class does allow you to read the property:
public Date getDate(){
return x;
}
And the Date class allows you to set its property:
d.setMonth(12);
No private member is being accessed outside of a class here. Date and A are two different classes.
This did not change x it is still pointing to the same object. What was changed is the object itself.
You are confusing reference with value.
The Date object referred to by x never changes and the field x is inaccessible from the sub class - ie the sub class can't assign a different Date object to x.
However, the getter allows you to access the object referred to by x, and (perhaps unexpectedly) Date objects are mutable - that is a Date's value can be changed. It's still the same Date object, but the instant in time it represents is different.
IMHO, the Date class is "broken"; it should be immutable.
The getDate() method is public. The getter method is public, that is you can now access the object and change its value. Date d and Date x are only reference to those objects not the actual objects.

Non-static method reference?

A little side project I've been doing for fun involves subtracting the current date from a future date given by the user to return the days between them.
public int getDaysBetween(int date2)
{
//Subtract current date from future date (date2), leaving the number of days between them
int getDaysBetween = 0;
Calendar myCalendar = Calendar.getInstance();
myCalendar.get(Calendar.DAY_OF_YEAR);
getDaysBetween = date2-Calendar.DAY_OF_YEAR;
return getDaysBetween;
}
The method for doing this is non-static, as the date2 int changes. However, when I try to reference it in my main class...
//Figure out a non-static reference
int date2 = Integer.parseInt(JOptionPane.showInputDialog("Enter a day in the year ahead of today"));
message = "Days bewteen: " + Date.getDaysBetween(date2-Calendar.DAY_OF_YEAR);
JOptionPane.showMessageDialog(null, message);
I get the error that a non-static method cannot be referenced from a static context.
I am fairly new to Java, so it might seem easy to most of you guys, but I could use the help.
Thanks in advance!
The method for doing this is non-static, as the date2 int changes.
I think you've misunderstood the meaning of the static modifier.
Your method doesn't use any instance fields, and there's no reason to override it in subclasses, so it should be a static method.
date2 is a parameter, so each call to it can pass a different value. That doesn't depend on the instance you call the method on.
(As an aside, it's not really clear what your method is meant to achieve - are you really interested in the day of year? It's also likely that java.time or Joda Time would provide a better API for this. However, it's most important that you understand what static means... you might want to read the Java tutorial on class members.)
Your method appears to have intended to return date2 minus the current DAY_OF_YEAR (not minus the DAY_OF_YEAR constant). And if you make it static then you don't need an instance like,
public static int getDaysBetween(int date2) {
return date2 - Calendar.getInstance().get(Calendar.DAY_OF_YEAR);
}
Assuming this is your own Date class, then to make it non-static (or an instance level) you would need to call it on an instance like
message = "Days bewteen: " + new Date().getDaysBetween(date2);
But if it's static then you can use
message = "Days bewteen: " + Date.getDaysBetween(date2);
Finally, please don't name your class Date (the JRE includes at least two classes with that name java.sql.Date and java.util.Date).
The method is not static. This means you have to have an instance of the class to use the function. E.g:
Date date = new Date(); // Create an instance of the Date class
date.getDaysBetween(...); // The method call is related to the instance
What you are doing is trying to call the method as if it were static. A static method does not need an instance of the class. Instead it is a feature of a class itself. This if you want to perform a static method call like this:
Date.getDaysBetween(...);
You need to declare the method static:
public static int getDaysBetween(int date2)
The method for doing this is non-static, as the date2 int changes.
Static variable is one that is shared between all the instances of the Class.
Static method is a method that can be invoked without the need for creating and instance on the class.
Variables that cannot be changed are called constants and declared with a keyword "final".
When you declare your method, you can make it static by adding a "static" keyword in method declaration like this:
public static int getDaysBetween(int date2){}
Otherwise, you can keep your method non-static, but in this case, to invoke it, you would have to create an instance of a class and then call method on that instance:
message = "Days bewteen: " + new Date().getDaysBetween(date2);

In Java how should I compare an object to a const value?

I've created my own MyDate class. It basically wraps a Long value with some pretty toString() functions. I've implemented equals() and compareTo(). my program reads some data and instantiates object of classes that hold this MyDate class. Problem is that sometimes that data is bad so I created a public static final long NODATE = Long.MIN_VALUE; so that I could initiate a new instance that is empty (replace the null in the containing class so to avoid NullPointerExceptions). I've also implemented a constructor with no arguments that inits the Long value to NODATE.
My Problem:
I want to check if a MyDate is valued as NODATE. I can't compare to NODATE since it's Long and not MyDate. One way to do this is:
if someObject.myDate.equals(new MyDate()).
But it seems like a waste to create an object just to make the comparison? Another way is to implement MyDate.amINoDate() method.
Is there another way? I was thinking of creating an static instance of MyDate that is inited to NODATE and to compare to it. But how can I compare my non static objects to this static object?
class MyDate {
public static final MyDate NODATE = new MyDate(Long.MIN_VALUE);
// ...
}
// ...
if (someDate.equals(MyDate.NODATE)) // ...
Thanks maskacovnik.
You can also add a method to MyDate like:
public boolean isNodate() {
return internalLongDate == Long.MIN_VALUE;
}
Add a method to MyDate:
if (someDate.isNoDate()) {
...
}
Also: personally I would avoid the Long.MIN_VALUE and use null.

Get/Set in java and reference

Get / Set methods are there to protect my class fields.
But since Java is working with reference my private fields are still getting exposed..
e.g.
private Date d;
Date getDate(){
return d;
}
void setDate(Date inD){
//Checks for inD
d = inD;
}
//Still the issue is
getDate().setHours(xyz);
What is the correct approach? Because i dont want to change my Date without using setDate.
Because i dont want to change my Date without using setDate.
Then you shouldn't return a reference to a mutable object in your get method. For example:
private Date d;
Date getDate() {
// Return a reference to an independent copy of the original data
return new Date(d.getTime());
}
void setDate(Date inD) {
// Checks for inD
d = inD;
}
A better approach (IMO) would be to use immutable types for your fields - the Joda Time API is a much cleaner date/time library and it has plenty of immutable types.
Now that was just an example of course - in other cases you might want to return an immutable view on a mutable object (which you would usually avoid mutating yourself) in order to avoid having to copy a lot of data on each get call.
There is a good approach for that which is called Defensive Copy,
Date getDate(){
return new Date(d.getTime());
}
you'll get a copy of it and original one will have no affect
Date is just an abomination since it is mutable. What you could do to make it safe, is to return a copy of the date. If that is modified, the original value is not changed.

Should I use the "final" modifier when creating Date objects? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
When should one use final?
When should Java programmers prefer to use
final Date now = new Date();
over
Date now = new Date();
Apart from deciding if a variable should be final or not which is covered in other posts, I think the problem with final Date now = ..., is that although the reference to now will not change (it is final), its value might. So I find this a little misleading for developers who don't know that Date is mutable.
For example, you could write:
public static void main(String[] args) {
final Date now = new Date();
System.out.println(now);
now.setHours(5);
System.out.println(now);
}
and get 2 different dates out of your final date...
Now this is true for any mutable variable (the content of final List<String> l can change too), but I think in the case of a Date, it is way too easy to assume immutability.
A better solution would be using the joda time library:
final DateTime now = new DateTime();
in this case, now is immutable and won't change (reference & value).
In Java, a final variable is a variable whose value, once assigned, cannot be changed. You declare a variable final when that variable will be assigned a value, and you will never need to change that value.
When you use final keyword you can never change the value of variable.Same apply for date.
A final variable can be explicitly initialized only once. A reference variable declared final can never be reassigned to refer to an different object.
However the data within the object can be changed. So the state of the object can be changed but not the reference.
With variables, the final modifier often is used with static to make the constant a class variable.
Example:
class Test{
final int value=10;
// The following are examples of declaring constants:
public static final int BOXWIDTH = 6;
static final String TITLE = "Manager";
public void changeValue(){
value = 12; //will give an error
}
}
if your requirement is of this type than you can use final with date.
If you declare a field, which is read-only, and you want to have a class thread-safe - then you should use the final modifier. Sometimes you're forced to make a variable final, if it's used in an anonymous class. In all other cases it doesn't really matter.

Categories