Mike Simmons

Master Rancher
+ Follow
since Mar 05, 2008
Merit badge: grant badges
For More
Cows and Likes
Total received
In last 30 days
Total given
Total received
Received in last 30 days
Total given
Given in last 30 days
Forums and Threads
Scavenger Hunt
expand Rancher Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Mike Simmons

This goes with my previous comments about 3rd-party plugins.  As I recall there were various times I had to remote debug with something like WebSphere or I forget what other products, and plugins existed to assist with this in Eclipse, but not IntelliJ.  (At the time.). So remote debugging would push you towards Eclipse.  Later, by the time IntelliJ had split into free and premium versions, IntelliJ was making sure the premium version would have all the plugins you were likely to need.  And many are now available in the free version as well.  So now, it's easy to remote debug with Intellij - but that wasn't always the case.
19 hours ago
Good point.  Though if the methods have incompatible return types but the same name, there's no way to fix that.  But making sure you could resolve the problem for compatible return types at least, that makes sense.

As I recall... my impression, at least... was that interfaces were intentionally kept simpler and more flexible than abstract classes, with the idea that you would never put an implementation in an interface, but that sort of thing would always go into a class, whether concrete or abstract.  There were always some loopholes in that idea, but they added much larger loopholes when they started allowing static, default, and private methods in interfaces.  But even then, they never violated the idea that a new implementation of an interface could provide a new implementation of each method.  That was the whole idea, originally at least.  And it seems that they're still clinging to it...
Interesting question.  I suppose they could change the rules to allow this, if they wanted to.  My guess is that they never saw a particular use case for it.  If someone does want to do this, they can also just make an abstract class instead, with a mix of concrete and abstract methods.  I'm guessing they wanted to keep the rules for interfaces a little cleaner.

Prahlad Yeri wrote:

Campbell Ritchie wrote:Why are you using a for loop rather than for‑each?

Is the speed difference between the two that big? I'm trying to optimize for performance here.

The speed difference is negligible.  The for-each is just simpler to use and read, and harder to accidentally insert an error into -- thus it's usually preferable unless you have a specific need for something else.
1 day ago
To be fair, I think the two ArrayDeques are more efficient than Carey's suggestion of using an ArrayList (with or without ListIterator), if you're adding characters anywhere besides the end of the string.  But a LinkedList traversed with a ListIterator will be more efficient, and more importantly, simpler to code correctly.
1 day ago
I don't think Stephan said that at all.  He's just pointing out that with try-with-resources you don't need a second try/catch to handle an exception during close() - it's all covered by the single try, if you add a catch - such as the one Stephan showed.

The implicit finally block (or any finally block) doesn't actually catch an exception.  If an exception is thrown, then the finally block will execute, putting a "pause" on the exception while finally executes.  But then when finally is done, it will continue throwing the exception as before.  Unless there is also a catch block for the exception.

For a checked exception, you do still need to either catch the exception, or declare that it can be thrown from that method.
1 day ago
True.  Often the hardest part is simply figuring out where in the JLS the rule you need is located.  But again, in this case that's pretty straightforward.  So I would say, it's worthwhile for programmers to get in the habit of at least trying the JLS as a source of answers... but it's also understandable if they don't always find it terribly helpful.
Yeah, I become extremely suspicious of any build that depends on any IDE-specific tools.  Largely because of some Eclipse-plugin-specific experiences many years ago.  But if the project can't be reliably built from the command line outside any IDE, that's a huge red flag for me.  As a result, I am suspicious of any IDE-specific file that gets checked in.  Though theoretically some may be things that merely enhance the experience for that particular IDE, which wouldn't be a problem.  I guess I'm reflexively paranoid about that stuff.
2 days ago
Of course, if Simon's course is paid content, it's unlikely we can get a shareable link.

I wonder, does Boyarsky & Selikoff explain that compound assignment operators have an implicit cast?  Of course, that's another paid resource, and I don't have a copy.  But I think Anil does...

Anil, I know the JLS can be a pain to read.  But it is often the best resource to explain some of the subtle points that slip through the cracks of other resources.
I think Eclipse also benefited from the fact that IBM put a decent amount of work into it before it was released to the public, and the early versions were pretty good by the standards of the day.  So it was appealing to many people from early on.  I don't know how true that was of NetBeans; the few times I looked at it I never saw something that kept me coming back.

Eclipse also cultivated a strong 3rd-party-plugin support culture from early on - which also ties into the free/open point.  So a lot of plugins were available.  Those plugins weren't always compatible, of course, and finding that out could be an adventure in itself...

In comparison, IntelliJ IDEA initially concentrated on making the basic code editing experience as smooth as possible.  Without necessarily having all the bells and whistles of the plugins.  Those came later, as far as I recall.
2 days ago
The legalistic, nitpicky,  but authoritative answer is given by JLS 12.4: Initialization of classes and Interfaces, and JLS 12.5 Creation of New Class Instances.  Specifically this section:

JLS 12.4 wrote:
7. Next, if C is a class rather than an interface, then let SC be its superclass and let SI1, ..., SIn be all superinterfaces of C that declare at least one default method. The order of superinterfaces is given by a recursive enumeration over the superinterface hierarchy of each interface directly implemented by C (in the left-to-right order of C's implements clause). For each interface I directly implemented by C, the enumeration recurs on I's superinterfaces (in the left-to-right order of I's extends clause) before returning I.

For each S in the list [ SC, SI1, ..., SIn ], if S has not yet been initialized, then recursively perform this entire procedure for S. If necessary, verify and prepare S first.

If the initialization of S completes abruptly because of a thrown exception, then acquire LC, label the Class object for C as erroneous, notify all waiting threads, release LC, and complete abruptly, throwing the same exception that resulted from initializing S.

8. Next, determine whether assertions are enabled (ยง14.10) for C by querying its defining class loader.

9. Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.

Item 7 boils down to initialize the superclass before any subclass.  Item 9 justifies printing "1"", and then "8", in the code given.

And then later, this section:

JLS 12.5 wrote:3. This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.

4. Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.

5. Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.

Item 3 boils down to perform instance initialization for a superclass before instance initialization of any subclass.  For the superclass Antelope, item 4 then justifies printing "2", and item 5 justifies printing "4".  Then for subclass Gazelle, item 4 justifies printing "9", and item 5 justifies printing "3".

There are probably other sources floating around that present that info in a more digestible manner.  But the JLS would be the official specification - warts and all.

1 week ago

Paul Clapham wrote:Let's have a go at that with String Templates:

I haven't tested this but I can see that the idea is still subject to futzing around to get the spaces in the right places.

Good call, thanks!  For a text block you need a new line after the opening """.  In this case, we can also use a text block with a regular string for the template, not a text block:
1 week ago
Although I don't really see a compelling use case for it, in theory I can buy the idea that some people might want to make a stream that fails if there are no elements in it.  As it happens, I was looking at Java 22's new Stream Gatherers feature, which purports to be a mechanism for adding arbitrary new functionality to streams as an intermediate method.  Much like Collectors can add arbitrary new features to Stream, except that Stream.collect(Collector) is a terminal operation, while Stream.gather(Gatherer) is an intermediate operation.  So, it's a good candidate for the use case here, which is to add fail-on-empty-stream functionality to a Stream without interfering with whatever other operations you wanted the Stream for.  Here's what I came up with:

This requires Java 22, and further requires enabline preview features:

But yes, it does work.  So, you may have to wait until September 2025 or so for a non-preview LTS implementation, but eventually, Java will allow this sort of arbitrary restriction to be inserted into a Stream.  Yay?  

Well, I was mostly interested in getting a handle on Gatherers, and this is a fairly simple case for that.
1 week ago
Also covered by Dr. Clapham a few months ago, above:

Paul Clapham wrote:Not all operators have an identity -- you'll find that subtraction doesn't have one, for example. That's why the documentation mentions that operators must be associative if you're providing their identity. Also, providing an incorrect identity will produce weird results.

1 week ago