Come on Greg. This is exactly my point. Why are you adding 1 to
Calendar.February in the first place? Are you trying to have bar ==
Calendar.MARCH? If you are, you just hosed yourself by assuming the
value
of FEBRUARY would not change.
There are actually two distinct points here, which you seem to be
conflating.
Point 1 is the proper use of predefined constants in source, such as
FEBRUARY. Point 2 is whether a predefined constant can be changed in
the
future without breaking existing compiled code, i.e. binary
compatibility.
They are related issues, but not at all the same.
My point is that you cannot do what you propose, i.e. change the
literal
constant value of FEBRUARY in the future. At least not without
breaking
binary compatibility.
This would be impossible to change whether or not any code anywhere
performs arithmetic or any operation at all on the value of FEBRUARY.
Something as apparently simple as equality via == would break if the
values
were changed. This happens because the literal value at the time the
referring class was compiled is in-lined into the referring class. So
if
you changed Calendar.FEBRUARY and didn't recompile all referring
classes,
those referring classes would break.
All this happens irrespective of anything I do with the int value of
FEBRUARY. If I just refer to the value at all, it's compiled inline:
every
time. Once that happens in any referring class anywhere, the value
can't
be changed without breaking binary compatibility.
Right. No argument here. If you change the value of FEBRUARY you need
to recompile all code that used it. This is what makes it highly
unlikely that Sun would ever do this.
I did not purpose that the value of FEBRUARY be changed. I just
suggested that it is possible that a class's implementation may change
over time. You should do you best not to depend on the values of
constants. In fact you should do your best not use primitive or String
literals for public constants.
By treating FEBRUARY as you would any other
int, you've screwed up. FEBRUARY represents the month February not 1.
The primitive int type exhibits certain characteristics like "order"
and
"successor". That is, ints can be ordered, for all int values, and
any int
value has a successor int value, for all values assignable or
comparable to
ints. (A successor is not necessarily higher in magnitude, i.e.
"greater
than", but that's a separate question.)
Months also exhibit "order" and "successor" characteristics. So
knowing
that FEBRUARY is defined as the int primitive type, why is it such a
problem if the ordering of months and the notion of "successor to
month"
map to the expression of those characteristics by ints? That is, why
is it
so strange for "successor to FEBRUARY" to be "successor to int value
expressed by FEBRUARY" or FEBRUARY+1?
Especially if the docs say that, which they do.
The docs are pretty clear that JANUARY is 0, FEBRUARY is 1, and so on.
Hence, there is a very clear order and successor nature to the defined
month names. (Sucessor breaks down after UNDECIMBER, which is also a
separate issue.)
The doc for:
public final static int JANUARY
/**
* Value of the <code>MONTH</code> field indicating the
* first month of the year.
*/
Are you talking about the documentation for the Date class? It has no
constants. Of course Calendar points to the values but I'm not sure
why. If they were important don't you think they would be on the same
page?
And let's not forget that the type of FEBRUARY is the primitive type
int.
That's a type, hard and fast. If it were something else, reference or
primitive, then conclusions about order and successor might not be so
easy
to infer, but only in the absence of documentation (and there is no
absence
of documentation, so the hypothetical point is moot).
If FEBRUARY were a Month type of some kind, then there aren't any
specific
rules about ordering or successor, because no reference type
implicitly has
such relationships. So you'd have to define ordering and successor
methods
and relationships in the definition of the class, if that mattered.
If it
didn't matter, or if you wanted to explicitly NOT define order or
successor, then leave those operations out.
Right.
To my
mind the error is that FEBRUARY is of type int, The whole point is
don't
assume anything about the values of constants other then what is
explicitly
documented.
No. That is the documentation for the class Date. That is an API and
not inherent to the language. If you'd like me to just accept this as
part of the Java language I won't. I will accept that that is the way
the java.util.Date class does things. But remember Date has no
constants. Take a look at the current documentation for Date. All
methods that deal with days, months, years, hours, etc. are
depreciated. If people would like to use the Date class's documentation
for its depreciated methods as gospel, so be it.
The fields are there to use in the invocation of the classes
methods, set(Calendar.MONTH, Calendar.FEBRUARY), etc. and to compare
the
equality of one month to another.
And the documentation also specifically says that the int values have
ordering and successor characteristics identical to the usual int
behavior.
So FEBRUARY+1 is the successor to FEBRUARY, i.e. MARCH. Guaranteed.
I yield. I am not going to argue this point any more. Based on the
documentation I can't win.
But the point remains it is a dangerous practice to assume the values
of
constants will remain the same over time.
Not true. Constants (defined as compile-time static final literals)
MUST
remain the same over time, or code breaks because binary compatibility
is
lost.
You are of course, right. You have to assume this in order to use
literal constants at all. Unfortunately, I've been burned before.
While it *IS* true that you cannot assume that named constant values
have
any particular value, ordering, successor-ship, relationship, etc.,
you CAN
assume that the values won't change, if binary compatibility is
maintained.
It is a consequence of the nature of binary compatibility.
Of course, if you toss out binary compatibility, then your existing
compiled code can break when things change in the future. Duh. That's
what breaking binary compatibility means.
This is depending on the
implementation and not the API of a class, thus defeating the purpose
of
separating the two.
If named public static final constants are in the public API of the
class,
then those values are part of the public API. Therefore, they can't
change
in the future, any more than you can change a public method's name or
arg-types or return-type and not have existing code break in the
future.
Calendar is an abstract class.
Just not *THAT* abstract.
Its an abstract class. It just has an unimaginative view of what types
of calendars can be dreamed up or it would be *MORE* abstract. ;-)
Suppose it were
extended to model a calendar in which JANUARY were not the first
month,
DECEMBER was. DECEMBER < JANUARY should be true.
Not possible for Calendar. The nature of how the constants were
defined,
as static final ints, absolutely prevents that from happening.
But Calendar.DECEMBER <
Calendar.JANUARY is false. We would want all Calendar instances to be
able
to work correctly.
You may want that, but it would be impossible to achieve, if binary
compatibility is also to be retained. You just can't get there from
here.
If Calendar had a successor() or predecessor() method, then that's a
different question.
While this example may appear artificial with respect
to Calendar, Its quite common in other domains.
That may be so in other domains. It might even have been possible when
Calendar was being designed. As it now stands, it's impossible to
achieve.
Hopefully, you are not
working on mission critical or life sustaining/threatening
applications.
It's a side issue, but the Java license does not permit Java to be
used in
such applications. See the license details. (May have changed over
time,
but it was certainly forbidden in early Java licenses.)
There are right ways and wrongs way to do things. Sometimes the wrong
way
is good enough for the moment. Its also the cause of bugs down the
road.
Your call.
And sometimes you have to accept what is. Calendar is what it is.
You can
argue it should have been something else, but it isn't something else,
it
is what is.
I do and it is.
That doesn't mean you can't define another class that's more in line
with
the something else you think Calendar should have been.
I have and believe it or not it uses GregorianCalendar to perform some
of its work.
But since Calendar has public static final ints in its public API that
define named months, there are some things that are absolutely
guaranteed
for those values, for Calendar to retain binary compatibility. That
the
literal numeric values (i.e. the bit-patterns) won't change in the
future
is one of those guarantees. This must be so regadless of whether you
do
arithmetic or ordering comparisons on the values or not. If the
bit-patterns change, code will break.
OK
I think I understand your points about abstractions and assuming too
much
about constant values. But we're talking about the concrete Calendar
class
here, and its public API expressed as methods and constant fields.
Not to
be redundant, but that public API is public, so Sun can't change it
without
breaking binary compatibility. That's in the nature of a public API.
But the values of the constants are not part of the API.
If you're talking about how to design a different Calendar-like class,
or
even a class that has nothing at all to do with calendars, and then
how to
express certain relationships (e.g. order and successor-ship) without
relying on primitive-type relationships, that's a different kettle of
fish
suitable for a different list.
Yes and I'm not.
Maybe I was too wide ranging in my responses to this issue and used
hypothetical examples that were highly unlikely to come to pass without
stressing their hypothetical nature. The point I wanted to make was
pretty simple. Sorry I was unsuccessful. I answered these posts in
haste and it obviously shows.
Glen Ezkovich
HardBop Consulting
glen at hard-bop.com
A Proverb for Paranoids:
"If they can get you asking the wrong questions, they don't have to
worry about answers."
- Thomas Pynchon Gravity's Rainbow
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Java-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/java-dev/email@hidden