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

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.

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.

convert mutable variable to immutable in java with less pain

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

Why we do not create object for static method in java?

Sometimes we call className.methodName() without creating object for it, I mean without using syntax as className objectName = new constructor() and then call as object.methodName()
When to use className.methodName()?
When to call method using object as object.methodName()?
Explanation of above two cases with example will be appreciated.
What you're referring to is a static method.
Assume that I have this :
public class A {
public static void foo(){
System.out.println("Hooray! I work!");
}
}
You can now do this anywhere else in any other class :
A.foo();
This is because the method is static, which means that it can be called on by the CLASS.
This means that it doesn't require an instance of that class in order for the method to be called.
However, even though it isn't required, you can still do this :
A a = new A();
a.foo();
But since the method foo() is static, instantiating an object A is not required in order to run the foo() method.
First. When you're create at least one static method of a class, you can use this method without creating an instance of class. This is useful, for example, for the creation of methods with independent logic. For example:
public class Checker {
public static Boolean month(int value) {
return (value >= 1 && value <= 12);
}
}
You need check correct value of month many times. But what to do each time to create the object. It is much effective to use a static method.
Second. When you create the object, the object is stored in the memory and you get a link to it. Then the object can be used for example to save at the list.
Method at this object is specific. You can save class data and do specific operation with member of this class. For example:
List<Animals> animalsList = new ArrayList<>();
Animal animal = new Animal("dog");
int legs = animal.getCountLegs(); // specific function for object
animalList.add(animal); //save if you need
// use list of object
For every class, we have a Object called as class object which is YourClass.class object. static methods are invoked based on meta-data on those objects. For instances of a class, methods are invoked on the actual instances. Both static and non-static methods are present on method area.
There is no different between 1 and 2 point, because in during compilation compiler makes ClassName.staticMethod() instead of instance.staticMethod().
Static methods in java belong to the class (not an instance of it). They use no instance variables and will usually take input from the parameters, perform actions on it, then return some result. Instances methods are associated with objects and, as the name implies, can use instance variables.

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);

global data, static and new

Basic question from somebody coming from structured into object programming... hoping not to be too basic.
I want to have a large array of data that is been shared by different classes inside my application.
What's the best practice to do this?
Is this correct?
public class LargeData {
private static long[] myData;
private static final int MAX = 100000;
public LargeData() {
myData = new long[MAX];
// ... initialize
}
public long getData(int x) {
// ... do whatever and return a long
}
}
And if this is correct, how is the correct way to access this data from any of my classes? Should I make a
LargeData ld = new LargeData();
inside every single class that wants to access to myData?
Thank you and sorry for being too easy... :)
use a Singleton pattern for this.
Everytime you call
LargeData ld = new LargeData();
in your code, you will be effectively calling
myData = new long[MAX];
which is wrong.
What you can do is:
public class LargeData {
private static final int MAX = 100000;
public static long[] myData = new long[MAX];
}
and access it as LargeData.myData from anywhere.
initialize array immediately. with current implementation you won't be able to use static array until create object of LargeData.
Also if class just for holding array prevent its instantiation and extension by making it final and constructor as private.
public final class LargeData {
public static long[] myData = new long[100000];
private LargeData() { }
}
And get access as LargeData.myData
Assigning values to static variables from instance constructors is a bad idea without a null check - if you ever instantiate two objects from this class the second will cause you to lose all data stored in the array (you lose the reference to the old array when the second instantiation overwrites the static reference). With null check it is also a bad idea though, unless you really really really need the data in one instance sort of a "global variable" way. It is best to think of static references as global variables which can be either viewable by all (if they are public) or visible only from the class you define it in (private) or something in between (protected or package protected access). You pretty much want to avoid using them though in almost all cases and use the Singleton pattern instead of static variables inside classes. With the Singleton pattern you use instance variables and non-static getters to get to the data.
However I do not see given the things you wrote why you would need a singleton pattern for this particular problem - you just want to store data in an object and share that object around, right?
You can fix the posted code like this without static keywords and this allows multiple LargeData instances to be alive at once in your application:
public class LargeData {
private long[] myData; // instance variable to store the data
private static final int MAX = 100000; // max length
public LargeData() {
myData = new long[MAX];
}
public long[] getData() {
return myData;
}
}
Then you can use the data as:
LargeData ld = new LargeData();
long[] = ld.getData();
And you can use the reference stored in ld any way you like, you can pass it around your other classes, etc.
A better idea would be to not expose the array, rather create an API through which you use the stored data. For example:
public long getLong(int n) { return myData[n]; }
public void setLong(int n, long value) { myData[n] = value; }
Now if you don't want to pass around the reference to the LargeData instance stored in ld, you can use a static variable in LargeData to store the reference and a static getter which lets you access it from any other java code. If you need multiple LargeData instances to work with you can create a LargeDataRegistry class that encapsulate a Map where you would store each instantiated LargeData instance.

Categories