I am a college student.
In our college we have to develop a simple Date class in Java similar to the one available in java.util package.
If we do that then what are the methods we can implement in that class,
Since most of the methods are deprecated in original Date class.
I saw the original Date class definitions in java/util/Date.java. Being a beginner to java, I could not understand the concepts of Serializable, Cloneable, Comparable ,and many variables like fasttime.
It will be good if we can implement this date class simply (since we have to develop this code as a test with in 3 hours at lab.)
Whether it is necessary to implement those concepts in a simple Date class.
If I take it as a Project and start developing the whole Date utilities,
then that code will run to many pages
and I cannot finish it with 3 hours for our lab session.
So someone please guide me....
I have doubts about....
Whether it is possible to create a utility class similar to Date class with a simpler implementation.
If we do that, then what are the methods we can implement in that class , since most of the useful methods are deprecated in the original date class.
Thanks in advance.
Serializable means the class can be Serialized to a transportable binary form.
Clonable means the class can be cloned, this is very tricky to get right, mainly because of inheritance and mutability concerns.
Comparable means the class supports being compared to other classes of the same type.
Of these Comparable is the only one that requires any code to function, it is also probably the only one that is any use in your scenario.
Serializable is what is called a Marker Interface it doesn't require any code to cause anything to happen since it doesn't have any methods to implement. It just exists to mark the object as supporting something and another class and check for this interface and do things based on its existence.
Cloneable is something you want to stay away from if at all possible. Cloning objects in Java is not straight forward, has lots of gotchas and generally behaves in the most non-intuitive ways imaginable. If you really want to know about this, learn about this, read this article.
Comparable is very valuable, it lets you compare to like objects to see if one is less than, equal or greater than another. This is a requirement for sorting and Collections classes that support Comparators. Comparators can be thought of as stand alone implementations of Comparable that can be plugged into other classes to control how objects are compared.
java.util.Date is a tricky class, it appears to be a straight forward struct type class with some mutators and convenience methods, but the underlying problem domain for calendar data isn't that simple. Calendar math has lots of exceptional cases. That is why there are so many methods on java.util.Date that are deprecated, they produced wrong behavior in many cases.
For some more code to study, look at this temporal package I developed to wrap the standard Java Calendar with very basic Date, Time and TimeStamp classes, they all just delegate to an instance of Calendar for the actual calcuations.
NOTE: this library code pre-dates JodaTime for those of you that might complain about just not using that library.
You don't have to implement all the interfaces to have a simple working Date class.
I would suggest that you forget about Java's Date class and consider what you think is needed for a date class. For example:
Get/set day of month
Get/set month
Get/set year
Get day of week
toString()
Would give you a pretty good basic date class.
For the sake of completeness, I'll tell you what the interfaces are for. You can decide whether to implement them based on how much you have learned and the assignment's requirements:
Serializable is for saving your object to a stream. You actually don't need to do much work to implement it.
Comparable is for comparing objects (date1.compareTo(date2) should return an integer indicating whether date1 is before, after, or the same as date2).
Clonable is for creating a deep copy of the object.
Since this is a lab project, why don't you list down what kind of function a 'simple' Date class needs and should have. For example, toString() -- returns a string representation of a Data or toMilliSecond() -- returns the number of milliSecond from the reference time.
Related
It may be very obvious questions, but is it good to use Enum class if you know that the list of values will keep increasing?
Let's say you define an Event Enum first it contains only [Poo, Too] then as we know we always have some new requirement it becomes [Poo, Too, App, Laa] and that keep changing again and again,
So what is the best approach in this case?
tl;dr
If the entire set of possible values is known at compile-time, use enum.
If values can be added or dropped while your system is in use (at runtime), then you cannot use an enum. Use a Set, List, or Map instead.
Known at compile-time
An enum is appropriate when the domain (set of all possible values) is known at compile-time.
If this year your company is offering two products ( Poo & Too ), then make an enum for those two elements.
public enum Product { POO , TOO }
Next year, your company decides to grow their product offerings by adding App & Laa. As part of a planned deployment, add two more objects to your enum.
public enum Product { POO , TOO , APP , LAA }
By the way, notice the naming conventions. The enum has a regular class name (initial cap). The objects being automatically instantiated are constants, and so are named in all-uppercase.
Also, be aware that the enum facility in Java is quite flexible and powerful, much more so than the usual naming-a-number enum scheme seen in most languages. You can have member variables and methods and constructors on a Java enum. For example, you can add a getDisplayName method to provide text more appropriate to a user-interface than the all-caps object name, as seen in DayOfWeek::getDisplayName. You can add quite a bit of functionality, such as ChronoUnit.between.
What you cannot do at runtime with an enum in Java is add or remove objects. Thus the requirement that you know your domain at compile-time. However, when working with a group of enum objects, you can use the highly-optimized EnumSet and EnumMap classes.
Known at runtime
If you cannot determine the domain at compile-time, if users can add or remove elements at runtime, then use a collection such as a List, Set, or Map rather than an enum.
Singleton
Though not originally intended as a purpose of Enum in Java, an enum happens to be the safest (and simplest) way to implement the Singleton design pattern.
This approach to a singleton is explained in the famous book Effective Java by Dr. Joshua Bloch, et al. Using an enum solves multiple obscure technical problems with other approaches to a singleton.
Your question is pretty generic and I'm pretty sure there is no single right answer. But judging based on spring* tags, I suppose you might be asking about enums in DTOs that being sent over your system in serialized form. If that's the case, I would recommend to choose String in DTO, while inside single app it's ok to use enum. Then you would just care about deserialization/conversion in a factory manner, having ability to handle unknown/missing constant gracefully by logging/providing fallback or meaningful error.
It depends on a case-by-case situation and your question doesn't have much context. However, I do recommend using ENUMs for many cases, including if you expect the list of ENUMs to increase.
Some reasons to use them are:
It creates a definite guide of ENUM elements that can be used throughout your code. It eliminates uncertainty over what something is named or what it is. For example ENUM that contains list of animals, or enum of "something".
Its easy to refactor later if you need to change anything.
I'm sure there are many more reasons, I find it like a table of contents sometimes. For many cases, you can completely avoid it and be fine but I think its better to use it in general if you're on the fence.
serialVersionUID seems to me to have a very loose specification. Any body developing a class with serializable interface can burn his hands with InvalidClassException. Also, i saw a fellow dev using int as a datatype rather than long.
So, my question why the Java designers and developers did not do something more concrete like whenever we implement serializable we have to implement a method setting serialVersionUID like the hashcode method.
So, what am i missing ? Does not seem like a double edged sword to me.
Update 1:
My bad i gave a wrong example comparing a class level thing with a instance level thing.I have seen many production issues across different companies because of this. But my general idea was cant it be made more strict by compiler in any way.
Keep in mind the requirements:
the bytes making up the ID must be present within the stream of bytes representing a serialized object
unless you invent something "on top", the only way to get there is by using a field
the ID must be identical for all objects of a class, thus the source of the ID should be static
Now step back:
there is no polymorphism for static methods
in that sense, it doesn't make a difference if you use a static field or call a static method to acquire the ID bytes when serializing an object
but you are going to write those bytes into the stream anyway
Conclusion: using a static field addresses all the above points
. When you would be using a method - you still have to create that field. Let that sink in: when using a method, the implementation must call the method, write that as field into the byte stream - and when reading the byte stream, that number needs to be consumed - as it can't be mapped to a "real" field in the class. Compare that to: there is a static field that gets written into the byte stream and read from there.
So - from a technical point of view, the natural way to integrate such in ID somehow is by asking for a static field on the class.
Of course you could have invented something else. Modern day java might have used annotations. But such usage of annotations wasn't around when Java was invented (and this kind of serialization is in Java since day 1).
And then: modern day java doesn't use "byte stream" oriented serialization in the first place.
Or as the answer from Stephen suggest - you could compute that ID based on the current content of the class. But again: this technology was invented 20 years ago. Back then, computing the id might have cost you 1, 5, 10 seconds. Compare that to the efforts of reading a static field.
So, my question why the Java designers and developers did not do something more concrete like whenever we implement serializable we have to implement a method setting serialVersionUID like the hashcode method.
If I understand you correctly, you are saying that there should be a method to calculate the serialVersion. I can see problems with this:
How would an application program calculate a decent serial version? Note that it must be calculated from type information ... not the values of fields.
Calculating a serial version at run time (repeatedly) would be expensive.
If we have lazy programmers who don't use the "serialver" tool to calculate a proper version number, the same lazy programmers are likely to implement this (hypothetical) method to return a bogus number ... and we are back where we started.
There are use-cases where NOT changing the serial version ID is intentional.
No. The real solution to the problem of lazy programmers is code reviews.
Or ... maybe ... tooling to either regenerate the serialVersion constants, or flag them as suspicious.
Note that tools can't pick all of the cases where there is going to be a problem. However, neither can a code-reviewer. And code-reviewers get tired, have to be paid, etc.
(Finally, it might be a good idea if certain IDE's didn't offer setting the constant to -1 as a quick-fix ...)
But my general idea was cant it be made more strict by compiler in any way.
It is not a compiler thing. It is a runtime behavior of a specific set of library classes. The classes use Unsafe ... but the compiler is not aware of the significance of the serialVersionID variable.
Why the Java designers and developers did not [make us] have to
implement a method setting serialVersionUID
The serialVersionUID is data related to the class. It's not data related to a single instance of the class.
If we had an interface such as:
interface MySerializable
{
long getSerialVersionUID();
}
then we could implement that like this:
class Foo implements MySerializable
{
private String myField;
//...
public long getSerialVersionUID()
{
if(myField.equals("hello"))
{
return 1L;
}
else
{
return 2L
}
}
}
This doesn't make sense. The version cannot depend on the instance.
Now that we have annotations, a good solution in my eyes would be to write a #Serializable annotation. I prefer this because anything related to serialization is really just metadata. Adding an additional field completely unrelated to the class's behaviour just muddies the water.
#Serializable(ID = "1")
class Foo
{
//...
}
Of course, annotations are a more recent addition so this wasn't an option when serialVersionUID was devised.
I have implemented a few Java classes which extend the abstract java.lang.Number class. I have no immediate need for serializing objects of these classes. However, I do want to provide the rest of the Number contract for these classes which represent "numbers." The trouble is that java.lang.Number implements Serializable. As such, my classes are supposed to provide public default (i.e. no-args) constructors -- my IDE complains, but the compiler will still compile my classes. Fine, but providing public default constructors for "immutable" objects requires providing a default value when the constructor is invoked for any reason other than serialization -- ignore for the moment that these classes return objects from static factory methods and expose no public constructors now. Well, zero is a fine default in many cases, but natural numbers -- i.e. positive integers -- do not include zero in their domain and no single number is any more "special" than any other...O.K...."one" is always "special"...
Etc., etc., etc....
I did look into how BigDecimal handles Number and Serializable in an effort to determine the "right" way to address this question. However, both the JavaDoc and the source code I have been able to examine reveals BigDecimal does not provide a "no-args" constructor despite having extended Number. Realizing that:
Just because Sun Microsystems/Oracle implemented it that way doesn't make it "right."
I am back to the basic question:
What is the "right" way to extend java.lang.Number? If providing a "no-args" constructor is just another Java convention following the rule:
It's not a law, just a good idea...
Is the best answer to avoid the warts by ignoring the "convention?" If so, how can I satisfy an IDE -- Intellij, in particular -- and any Java-to-other-language-or-environment translator which might choose to be more strict than the Java compiler when Serializable raises its ugly head?
Well, there's always good ol 'NaN' -- Not a number. If you can represent it, that is.
My opinion is that one could forget about being compatible with Java's built-in serialization after looking at the benchmarks. It's 8x slower than textual Jackson and seems being just outdated.
You can also make the empty constructor protected, this way serialization still works. What Sun did for BigDecimal was providing readObject and writeObject methods , see here for further details.
It seems to be the standard so I have been going along with it so far, but now I am building a new class from scratch instead of modifying the old ones and feel I should understand why I should follow the projects convention.
Almost every class has an interface to it which is called classnameable. In the code database.class would never appear even once but in place where I would want to use that class I see databaseable.class.
To my understanding an interface was a class that was never implemented but was inhereted from to keep standards. So why are the interfaces being used as if they were real classes?
To my understanding an interface was a class that was never
implemented but was inhereted from to keep standards. So why are the
interfaces being used as if they were real classes.
This is a bit confused. An interface defines an API, so that pieces of code from different authors, modules or projects can interact. For example, java.util.Collections.sort() can sort anything that implements the List interface and contains objects that implement the Comparable interface - even though the implementation classes may not have existed yet when the sorting code was written!
Now the situation in your project seems to reflect an unfortunately rather common antipattern: having an interface for everything, mostly with a single implementation class, even for internal classes.
This used to be strongly promoted by proponents of Test-Driven-Development (TDD) who see it as vital to be able to test every class in isolation with all its dependencies replaced by mock objects. Older mocking frameworks could only mock interfaces, so to be able to test every class in isolation, all inter-class dependencies had to be through interfaces.
Fortunately, newer mocking frameworks can mock concrete classes and don't require you to pollute your project with unnecessary interfaces. Some people will probably still argue that it should be done anyway to "reduce coupling", but IMO they're just rationalizing their desire not to change their practices.
And of course, if you don't do fundamentalist TDD, there never was a good reason to have an interface for everything - but very good reasons to have interfaces for some things.
If you've got an interface for pretty much every single class in your project even though there's no reason for it, that's not a good thing and in this day and age there's no great reason for it. It may be a legacy from days gone by when it was required by some external testing toolkit for instance - but these days that's not a requirement.
It may be of course that someone's heard that loose coupling is a good thing, that you should always couple to interfaces and not concrete classes, and taken this idea to an extreme.
On the other hand, it is good practice to define interfaces for some classes even if there's only one of them (at the moment.) When I'm writing a class I try to think along the lines of whether another (potentially useful) implementation could exist, and if so I'll put an interface in. If it's not used it's no problem, but if it is it saves time and hassle and refactoring later.
If you want a class for your interfaces then a common way is to create an AbstractFoo class to go with the Foo interface. You can provide simple implementation of the required methods, allowing derived classes to overwrite them as needed. See AbstractCollection for an example of such a class.
The advantage is that you don't have to implement all the small stuff, it is already done for you. The disadvantage is that you can't inherit from any other class. You pays your money and you takes your choice.
A good indication for bad design is when you have a ISomething or a SomethingImpl. The interface name should state how to use it (i.e. List), the class name should state how it works (i.e. ArrayList).
If you need pre- or suffixes because the names would be the same, this means there is only one way to implement it, and then there is probably no need for a separation. (If you think there will be more sophisticated implementations in the future, name your class DefaultSomething or SimpleSomething)
Is it confusing to design an API with multiple ways of achieving the same outcome? For example, I have my own Date library (which is a simple wrapper around the Java Date/Calendar classes to distinguish a year-month-day, Date, from an instant-in-time, Instant and provide mechanisms to convert between the two). I started off with one method to create an instance of a Date:
Date.valueOfYearMonthDay(int year, int month, int day);
But then I found that the resultant code using the API was not very readable. So I added:
Date.yearMonthDay(int year, int month, int day)
Date.ymd(int year, int month, int day)
Date.date(int year, int month, int day)
Then I started getting fluent:
Date.january().the(int day).in(int year);
(I find that the fluent version is really useful for making readable tests). All these methods do identical things and have accurate JavaDoc. I think I've read that a strength of perl is that each programmer can choose exactly which method he/she prefers to solve something. And a strength of Java is that there is usually only one way of doing things :-)
What are people's opinions?
I've been doing academic research for the past 10 years on different issues that have to do with API usability in Java.
I can tell you that the statement about having one way to do things in Java is fairly incorrect. There are often many ways to do the same thing in Java. And unfortunately, they are often not consistent or documented.
One problem with bloating the interface of a class with convenience methods is that you are making it more difficult to understand the class and how to use it. The more choices you have, things become more complex.
In an analysis of some open-source libraries, I've found instances of redundant functionality, added by different individuals using different terms. Clearly a bad idea.
A greater problem is that the information carried by a name is no longer meaningful. For example, things like putLayer vs. setLayer in swing, where one just updates the layer and the other also refreshes (guess which one?) are a problem. Similarly, getComponentAt and findComponentAt. In other ways, the more ways to do something, the more you obfuscate everything else and reduce the "entropy" of your existing functionality.
Here is a good example. Suppose you want in Java to replace a substring inside a string with another string. You can use String.replace(CharSequence, CharSequence) which works perfectly as you'd expect, literal for literal. Now suppose you wanted to do a regular expression replacement. You could use Java's Matcher and do a regular expression based replacement, and any maintainer would understand what you did. However, you could just write String.replaceAll(String, String), which calls the Matcher version. However, many of your maintainers might not be familiar with this, and not realize the consequences, including the fact that the replacement string cannot contains "$"s. So, the replacement of "USD" with "$" signs would work well with replace(), but would cause crazy things with replaceAll().
Perhaps the greatest problem, however, is that "doing the same thing" is rarely an issue of using the same method. In many places in Java APIs (and I am sure that also in other languages) you would find ways of doing "almost the same thing", but with differences in performance, synchronization, state changes, exception handling, etc. For instance, one call would work straight, while another would establish locks, and another will change the exception type, etc. This is a recipe for trouble.
So bottom line: Multiple ways to do the same thing are not a good idea, unless they are unambiguous and very simple and you take a lot of care to ensure consistency.
I'd echo what some others said in that convenience methods are great, but will take it a step further - all "convenience" methods should eventually call the same underlying method. The only thing that the convenience methods should do other than proxy the request is to take or return variables differently.
No calculations or processing allowed in the convenience methods. If you need to add additional functionality in one of them, go the extra mile and make it happen in the "main" / "real" one.
Its fine to provide convenience methods, the real problem is if each entry point begins to do behave in subtly different ways. Thats when the api isn't convenient anymore. Its just a pain to remember which way is "right," and documentation starts saying "the recommended way is..."
If Date.yearMonthDay() began to validate the date while Date.ymd() didn't, that'd be a problem. The same goes for if each begins supporting different "features" - Date.yearMonthDay() could take non-gregorian dates, and Date.date() could take a non-gregorian dates so long as a 4th object is given that tells the calendar type.
First, please don't invent your own date library. It's too hard to get right. If you absolutely have nothing better to do, be sure to read -- and understand -- Calendrical Calculations. Without understanding Calendrical Calculations you run a big risk of doing things wrong in obscure corner and edge cases.
Second, multiple access to a common underlying method is typical. Lots of Java library API methods state that they are simply a "wrapper" around some other method of class.
Also, because of the Java language limitations, you often have overloaded method names as a way to provide "optional" arguments to a method.
Multiple access methods is a fine design.
If these do the exact same thing:
Date.yearMonthDay(int year, int month, int day)
Date.ymd(int year, int month, int day)
Date.date(int year, int month, int day)
I think that is bad form. When I am reading your code, I have no clue which one to use.
Things like
canvas.setClipRegion (int left, int top, int right, int bottom);
canvas.setClipRegion (Rect r);
are different in that it allows the caller to access the functionality without having to figure out how to format the data.
My personal opinion is that you should stick with one method to do something. It all 4 methods ultimatly call the same method then you only need on of them. If however they do something in addition to calling them method then they should exist.
so:
// This method should not exist
Data yearMonthDay(final int year, final int month, final int day)
{
return (valueOfYearMonthDay(year, month, day));
}
The first methid in addition to the fluent version would make more sense. But the yearMonthDay, ymd, and date methods should go.
Also, differnt langauges have different goals. Just because it makse "sense" in Perl doesn't mean it makes sense in Java (or C#, or C++, or C, or Basic, or...)
I find that the fluent version is really useful for making readable tests.
This is a little bit troublesome because I worry that you might only be testing the fluent version. If the only reason methodX() exists is so you can have a readable test for methodY() then there is no reason for one of methodX() or methodY() to exist. You still need to test them in isolation. You're repeating yourself needlessly.
One of the guiding principles of TDD is that you force yourself into thinking about your API while you're writing your code. Decide which method you want clients of your API to use and get rid of the redundant ones. Users won't thank you providing convenience methods, they'll curse you for cluttering your API with seemingly useless redundant methods.