Steven Elliott

+ Follow
since Mar 28, 2002
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 Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Steven Elliott

No, that's not what they're saying. They're saying that even if o1.equals(o2), both will be allowed in the set unless you override hashCode.

I guess what I was looking for was BOTH o1.equals(o2) AND o1.hashCode() == o2.hashCode() need to be true otherwise the two objects will be inserted into the Set. I just didn't read it that way in the explanation.

The JavaDoc actually says for add(e)

Adds the specified element to this set if it is not already present (optional operation). More formally, adds the specified element e to this set if the set contains no element e2 such that (e==null ? e2==null : e.equals(e2)).

Apparently it assumes the contract for equals such that if o1.equals(o2) then o1.hashCode() == o2.hashCode() is true.
On page 563 of SCJP 6 by Sierra and Bates the following:

When using HashSet or LinkedHashSet, the objects you add to them must override hashCode(). If they don't override hashCode(), the default Object. hashCode() method will allow multiple objects that you might consider "meaningfully equal" to be added to your "no duplicates allowed" set.

Since equals() not hashCode() determines what is a duplicate in HashSet I don't understand the above. Even if two objects o1.hashCode() == o2.hashCode() is true but o1.equals(o2) is false both o1 and o2 will be added to the Set. The above quote seems to indicate that if the hashCode is equal determines what is considered to be a duplicate object... or maybe I'm not reading it correctly.

.hashCode() only determines the efficiency of Set operations like add and remove... and hashCode() should never be used to determine uniqueness.
I'm just a Greenhorn but to teach is to learn...

Threads calling non-static synchronized methods in the same class will
only block each other if they're invoked using the same instance and if
they're called using two different instances, they get two locks, which do not interfere with each other.

Quick review:
  • non-static methods are instance methods and execute within the scope of the instance.
  • static methods are class methods and execute within the scope of the class.

  • Your quote states that the threads are calling non-static or instance methods and not class methods. I'll cover both but first non-static methods.

    In order to execute instance methods you need to create an instance. For example MyClass newInstance = new MyClass();
    Lets say that MyClass has a non-static synchronized method as follows;

    public synchronized void instanceSyncMethod() { System.out.println("calling instanceSyncMethod()"); }

    newInstance is now an object with its own variables and methods. If newInstance is passed to two threads running simultaneously then both threads are using the same instance. So when thread1 calls newInstance.instanceSyncMethod() and thread2 calls newInstance.instanceSyncMethod() they are both asking the same object to do the same thing. Because the method is synchronized meaning only one thread can execute the code at a time the first thread to obtain the lock will execute and the second thread will need to wait/block.

    Lets create another instance of MyClass and call it newInstance2 - MyClass newInstance2 = new MyClass()
    newInstance2 is a separate copy of MyClass and has its own variables and methods. Now pass newInstance to thread1 and newInstance2 to thread2. When thread1 calls newInstance.instanceSyncMethod() and thread2 calls newInstance2.instanceSyncMethod() the two threads are calling the same method but on two different instances. Since each instance has its own variables and methods the threads run without blocking.

    Hopefully that makes the non-static part clearer.

    The static part requires that you change the scope (and thinking) from instance to class.

    Lets say that MyClass has a static synchronized method as follows;

    public static synchronized void staticSyncMethod() { System.out.println("calling MyClass.staticSyncMethod()"); }

    We have already seen that when thread1 calls newInstance.instanceSyncMethod() and thread2 calls newInstance2.instanceSyncMethod() that the two threads run without blocking. But what happens when they both call staticSyncMethod() even on different instances of MyClass?

    Because staticSyncMethod() is a static method only one copy of this method will ever exist and is referenced from the MyClass object. In fact when thread1 or thread2 calls newInstance.staticSyncMethod() the compiler is building a call to MyClass.staticSyncMethod(). The ability to use newInstance or newInstance2 to reference staticSyncMehtod() is allowed by the compiler as a convenience method but the code generated always translates the code to reference the class object.

    If you were to correctly program the code thread1 would call:
    and thread2 would call:

    It makes it easier to see that both threads are calling the same method in the same scope and by calling this method one thread would need to block as the other executed.

    Make sense?

    An anonymous subtype of Test.

    Yeah. Expands the general understanding of where you might find an anonymous inner class but a common enough usage to find as a parameter.

    I would be surprised if something like this appeared on the test but it might get asked at an interview.
    I had to reply to this to clarify what seems to be a misunderstanding regarding abstract classes and constructors and whether or not an abstract class can be instantiated.

    The contract of an abstract class is that the first concrete class must implement all abstract methods. In fact the abstract class itself can do this and by providing a concrete implementation of the abstract method(s) when instantiated.

    Here is a really simple example:

    The Test instance reference in AbstractTest is instantiated using new Test() and provides the concrete implementation of getI(). The compiles and runs returning:
    test 1 = 10

    What is interesting is if you add the following to the main method:
    System.out.println("Test classname = "+at.test.getClass().getName());

    will return "Test classname = classes.AbstractTest$1" indicating that Test has been compiled as an inner class of AbstractTest...! What kind of inner class?

    What is then interesting is if you test instanceof:
    System.out.println("at.test instanceof Test = "+(at.test instanceof Test));

    Will return "Test instanceof Test = true"

    The answer is yes, you can instantiate an abstract class... more or less;)

    Hey thank you Bert. Your book has been a great help and as you note knowing the number of correct answers will be a clue as to "which is/are the most correct".
    The other two are:

    B. The output is 987.12346 987.12345
    F. The code compiles and runs without exception

    I mistakenly posted this here and have reposted to the Programmer Certification (SCJP/OCPJP) forum where I had originally intended. The entire question and answers are posted there.
    12 years ago
    Here is the complete question 13 from Chap. 6 S&B

    @Prithvi: I agree that throwing an Exception in main() is not usual nevertheless doing so allows the program to compile and run as normally as you would expect. Moreover had this been any other method there would be no question that declaring the Exception would be a valid option (rule "handle-or-declare") as is the case for all checked exceptions.
    Somehow this ended up on Java Porch forum. Reposting here where I thought it I had posted it originally.

    Sierra & Bates SCJP 6 chap. 6, question 13 is:

    One of the correct answers is:
    G. The invocation of parse() must be placed within a try/catch block

    My nit is you can declare to throw an Exception in the main method so "...must be placed within a try/catch block." is not true because it is not the only option. I would be upset if I had missed this by not marking this as a correct answer because the way it is worded.
    Sierra & Bates SCJP 6 chap. 6, question 13 is:

    One of the correct answers is:
    G. The invocation of parse() must be placed within a try/catch block

    My nit is you can declare to throw an Exception in the main method so "...must be placed within a try/catch block." is not true because it is not the only option.
    12 years ago
    I would recommend that you organize your groups using Agile methodologies. Doing so will add to your overall experience besides being a good way to organize and meet goals. Base scrums on the Sierra/Bates book (the role of Product Owner).
    For instance a group of you (the team) would commit to beginning the cycle a certain date. The first task would be to complete Chaper 1, Declarations and Access Control... say in 7 days time. So day 1 sprint 1 would cover Identifiers & JavaBeans (Objectives 1.3 and 1.4). Day 2 sprint 2 would cover Declare Classes (Exam Objective 1.1). Day 3 sprint 3 would cover Declare Interfaces (Exam Objectives 1.1 and 1.2). Day 4 sprint 4 would cover Declare Class Members (Objectives 1.3 and 1.4).

    Whether or not it is realistic to cover all sprints in 1 day or 2 or 3 the important part is that at the end of the sprint you have accomplished the goal. Each day the group would meet to discuss how each member was doing and provide encouragement to those members having trouble keeping up as well as to discuss questions about the material. At the end of the initial sprints would come one sprint which dealt with Two-minute Drill and another with the Q&A. It might be a good idea for the members to use other mock exam sites as well as the questions at the end of the chapter.

    After the group finished with the first chapter (sprint cycle) to move on the next. It might be a good idea to build into the sprints a review of past chapters by going over the Two-minute Drill (retrospective).

    I'll do some more work on how this might be setup in Google Groups but maybe there is already an Agile Project Management site with some of the facilities to do this?
    The subject line is the best I could do to describe something that caught me out in the first series of self-tests, question 3 in the SCJP Sierra/Bates book.


    So you have the same method called with two different method signatures.
    The test question is:
    Which, inserted independently at line 6, will compile? (Choose all that apply.)
    A. static void doStuff(int... doArgs) { }
    B. static void doStuff(int[] doArgs) { }
    C. static void doStuff(int doArgs...) { }
    D. static void doStuff(int... doArgs, int y) { }
    E. static void doStuff(int x, int... doArgs) { }

    I answered A as the only correct answer and was surprised to find that E also is correct! The reason I didn't pick E was in the first case, doStuff(1), would not compile because it would be missing the varargs argument (there is only one argument, 1, after all). Surprisingly, though, not only does the code compile but it runs.

    Can someone enlighten me why doStuff(1) (w/one argument) will compile and run with E which requires two arguments?

    Jeet Jain wrote:In the 2nd file it gives an error at (4) saying it wants M instead of N. When I make it M it gives error at (3) saying same erasure as (1). I'm confused.

    What I find particularly tricky are the get() in SubC1 and SubC2.

    In SubC1 the get() as you note, will give a compiler error because the return type should be M and not N. When you change the return type to M the SubC1 correctly overrides the method in the parent class SupC and the compile error goes away.

    In SubC2, though, you don't get the same compile error presumably because N extends M. This would seem to imply that the rule to override is somehow validated if the return type is a subclass of parent return type. But if you tried to cast M to N you would see that won't work.

    So I am a bit lost as to why get() in SubC2 legally overrides the get() in SupC.

    Bear Bibeault wrote:The EL is part of JSP and will be enabled if you declare the web.xml correctly (see JSP FAQ). Download the Jakarata version of JSTL 1.2 (single jar file) and drop it into WEB-INF/lib.

    I don't believe Jakarta has a release version of JSTL 1.2 (yet). The Sun version can be had from

    As Bear mentioned your taglib will need to include jsp/jstl not just jstl.

    I believe you will need these to run TC6 from Eclipse.

    have fun!
    15 years ago