Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Monday, February 26, 2018

Java's Stack Class and Queue Interface

Neither java.util.Queue nor java.util.Stack enforce queue or stack disciplines. As such they are unsuitable for teaching queues and stacks, and unsuitable for use in software engineering.

If I have a Stack that is shared among various modules, perhaps maintained by various people, I want to know that no one is accessing it beyond push and pop at the top. Otherwise, there is no way to have any confidence that any contract or class invariants are being maintained.

I have no issue with Stack methods empty(), peek(), pop(), or push(). My objection to search is minor: this isn't part of the idea of the stack, so it should not be in the public interface.

But Stack also inherits a number of methods from java.util.Vector, including removeElementAt() and insertElementAt(). This is not a stack. It can be used as a stack, but the programmer has no assurance that other pieces of code are treating it as a stack.

The Queue interface is not as bad. The interface's six methods make it look like the committees that added to it over time were a  bit confused or at least not in agreement with one another, but, nonetheless, insertion is always at the tail, and removal is always at the head.

But Queue extends java.util.Collection, which adds a number of non-queue-like methods. Many of these methods allow treating a queue like a stream, which is more convenient than removing item-by-item, deciding if each item fits some criteria, and then adding those meeting the criteria back into a queue.

My main issue with java.util.Queue is shared with java.util.Stack: the is-a relation does not work. A subclass of either could satisfy the Liskov substitution principle, but the child would be neither stack nor queue.

One fix would be to define more reasonable Stack and Queue classes, and declare them final. What I really want is a way to declare an interface that restricts the addition of methods.

Monday, February 17, 2014

Java's java.util.Date Class

Teaching Java programming to novices forces me to sometimes revisit the basics in my own understanding, or the edges of what I understand.

java.util.Date has come up a couple times this semester, and I thought I would verify the behavior of Date for dates at and before 1970-01-01. Here's my simple test code:

//Time-stamp: <2014-02-17 11:14:34 jdm>

import java.util.Date;

public class TimeZero {

  public static void main(String[] args) {

    final int yearsAgo = Integer.parseInt(args[0]);
    final double msAgo = yearsAgo
      * 365.25 // days per year
      * 24     // hours per day
      * 60     // minutes per hour
      * 60     // seconds per minute
      * 1000;  // ms per second
    final Date d = new Date((long) -msAgo);
    System.out.println(d);

  } // main()

} // class TimeZero

I'm neglecting leap seconds in my calculation of ms before 1970-01-01 (called msAgo). Assuming that a year averages 365.25 days is also not quite right, but since 2000 was one of those leap years divisible by 400, it's pretty close for recent years. Providing zero as input acts as expected (once one takes the time zone difference between here and Greenwich into account):

> java TimeZero 0
Wed Dec 31 19:00:00 EST 1969

Three years earlier seems to be about right, given that 1968 was a leap year:

> java TimeZero 3
Sun Jan 01 01:00:00 EST 1967

1000 years before 1970 looks good:

> java TimeZero 1000
Sat Dec 18 19:00:00 EST 969

Let's look around near the beginning of CE and the end of BCE (boundary conditions):

> java TimeZero 1967
Tue Dec 19 01:00:00 EST 2
> java TimeZero 1968
Sun Dec 18 19:00:00 EST 1
> java TimeZero 1969
Sat Dec 18 13:00:00 EST 1

This seems odd, but the Gregorian calendar does not have a year zero (see https://en.wikipedia.org/wiki/Gregorian_calendar) and Date.toString() does not include CE/BCE indication. I played around with calendars in my locale to get the era, but cal.get(Calendar.ERA) returns an int, which makes no sense whatsoever, and the problem isn't interesting enough to spend more time on.

However, I am willing to say the Java Date and Calendar hierarchies are entirely too complicated for day-to-day uses. This is one of the few places where I endorse using non-standard class libraries.

Tuesday, June 5, 2012

Making OpenJDK 7 on Linux Mint 13 actually Work

I had a rude surprise last night after revising and recompiling some Java code: the compiler was, as intended, OpenJDK 7, but the interpreter was OpenJDK 6. So the program barfed.

OpenJDK 7 had previously been installed in the normal way (sudo apt-get install openjdk-7-jdk openjdk-7-source openjdk-7-doc), so that wasn't the problem. The problem was that in /etc/alternatives, some of the tools linked to JDK 6, and some to JDK 7. Blech. An obvious quick fix was to write a script to update all the soft inks, pointing all to OpenJDK 7. This seemed like a hack (in the original CS sense, where a hacker is a careless or unskilled programmer), so I decided to "do it right."

Uninstalling OpenJDK 7, uninstalling OpenJDK 6, and then re-installing OpenJDK 7 seems to have fixed things.

Thursday, April 1, 2010

Browsers

More and more I'm starting to use different browsers for different purposes. Opera is nice because it allows fine control over scripting on a per site basis. For example, at NFL.com, I can shut off most of the advertising but still use most of the site's features. I especially like this for Blackboard, however.

Blackboard is a commercial course management system. Essentially, it's bloatware loaded with features that I can't imagine many people use, but they persist because, apparently, someone uses each. One of the unfortunate features of Blackboard is that when entering data in a text area, it starts a Java application. Yes, an application, not an applet. For some inexplicable reason, Blackboard wants to run an application with full user privileges on my PC. This is even harder to understand, since disallowing execution seems to have no effect on Blackboard functionality. It's probably innocuous, but as a matter of policy, why subject all the data on my PC to Blackboard's whims and bugs? Plus, what, if anything, are the software folks at Blackboard thinking?

Firefox generates a warning, but doesn't remember negative decisions. It allows one to always trust a site, but not to always distrust a site. Strange.

Opera, though, now knows to never run Java at blackboard.umbc.edu. So far, this is causing no problems, and so Opera is now my browser of choice for Blackboard.

Monday, March 29, 2010

Private Data, Getters, Setters, and the Like

I'm not sure that I'm getting the rationale for class-level private declarations. Given that public "getters" and "setters" can access and even alter private data, what's the use of the private declaration in the first place?

Making data members private allows us to control access to them. First, most (probably) classes don't have setters and getters. Second, setters and getters can be instrumented so that accesses and changes can be tracked, logged, etc. This instrumentation can be useful for debugging. If a private field is getting set to a bad value, one just has to put debug code in the setter rather than hunting down every line that modifies the field.

Another reason, probably at least as important, is for maintenance, upgrades, etc. If I implement a structure with a private array today but later decide it should be a set or a list, I don't have to worry that the change will ripple through client code, breaking the installed base.

Finally, a class interface should have a specification, or a contract. If private data is being modified outside the class, it's not possible for the class to enforce the contract, and debugging the class spreads out from the class itself to the entire system. This complicates development and maintenance.

[suggested by a colleague an hour after I posted the above]
Setters can validate data, making sure it's in the correct range, consistent with other values, etc., before setting the field.