Thursday, May 29, 2008

String and StringBuffer

1.What is the difference between String s = "hello"; and String s = new String("hello"); ?

2. Why String and StringBuffer works differently, discrimination?

// Test.java
public class Test {
public static void main(String[] args) {
String s1 = new String("hello");
String s2 = new String("hello");
StringBuffer sb1 = new StringBuffer("hello");
StringBuffer sb2 = new StringBuffer("hello");
System.out.println("String: s1.equals(s2) = " + s1.equals(s2));
System.out.println("StringBuffer: sb1.equals(sb2) = " + sb1.equals(sb2));
}
}

// output
/*
String: s1.equals(s2) = true
StringBuffer: sb1.equals(sb2) = false
*/

A:

Since String class overrides the equals() method of Object class, and StringBuffer does not.
Read here: equals method and check the JDK doc for String and StringBuffer too.

3. How does Java String concatenation, or the overloaded + between different types, work?

A: Go to your JDK1.2.2/JDK1.3 directory, find src.jar, unjar it. Then you can see all source code of JDK.Goto src\java\lang, to find StringBuffer.java and String.java. Search for append in the beginning comments of StringBuffer.java, then follow the lead, you will find out all the secrets you are interested in. "If you give me a fish, You feed me for the day.
If you teach me how to fish, you feed me for life.
"

4. Why are outputs of these two statements so different?

System.out.println(6 + 4 + " = sum"); // 10 = sum
System.out.println("sum = " + 6 + 4); // sum = 64

A:

  • Java evaluates the expression inside println(expr) first, then convert it to a String.

  • When Java evaluates the expression, it follows the left-to-right rule.

  • "+" operator is overloaded in a very intuitive way just as in most other languages.

  • In 6 + 4 + " = sum": from left to right, evaluates 6 + 4 first, two integer adds, 10 resulted. Then 10 + " = sum", int plus a String, String concatenation assumed, converts 10 to a string, then ...

  • In "sum = " + 6 + 4: from left to right, "sum = " + 6, String plus an int, String concatenation assumed, converts 6 to a String, concatenates them together, become "sum = 6". Then repeats the same process with "sum = 6" + 4. You know the answer.

  • String concatenation process actually is finished by a class StringBuffer. If you want to know the details, read the source code of jdk: StringBuffer.java. It is highly recommended for you to do that.

Methods Overloading and Overriding

5. What is the basic difference between the concept of method overloading and overriding?

A: They are totally irrelevant except the name similarities in two senses.

sense #1: English words overriding and overloading both have "over" inside
sense #2:overloading methods will have the "same name" but different signature. overriding methods will have the "same name" and same signature.

Except these above, there is nothing in common between them. Please read some more from the following QAs.

6. Can overloaded methods in derived class hide the same name methods (with different signature) in base class?

A: When methods are defined with the same name, but different signature, they are just name overloading, nothing can hide anything else. It is irrelevant it is in a derived class or not.

  1. American people drive on the right side.

  2. You are right on this topic.

  3. He will be right back.

English word right is overloaded here, we understand the difference by the context. Compiler understands the method overloading by the signature, which serves the same purpose as context, but more reliable, since compiler is not as intelligent as you are. If derived class (subclass) defines a non-private method with the same name and same signature as the non-private method defined in base class, then it is method overriding, polymorphism comes into play. Late binding/Runtime binding will happen.Never mix these two words overriding and overloading, please.

7.Can overloaded methods be override too? Static binding or dynamic binding?

A: Yes, of course! In compiler point of view, overloaded methods are totally different methods. Because compiler identifies methods by their name and signature, you know overloaded methods must have different signatures.

Derived classes still can override the overloaded methods. Polymorphism can still happen. Compiler will not binding the method calls since it is overloaded, because it might be overridden now or in the future. It is compiler's responsibility to check the caller class has the method being called. It is the runtime's responsibility to call the right method along the hierarchy from bottom-up according to the real Object type identified.

8. What are the differences between overloading and overriding? Are they both concepts of polymorphism?

A: No, overloading is NOT a concept of polymorphism.

Let me try a short one about overloading. The approach is like you take the test, cross out something obviously not correct, before you decide what is correct. 3 + 5
3.0 + 5.0
The plus (+) operator is overloaded long before even OO concepts came into play in computer sciences. It is in Fortran (the first high level computer language) for sure.

  1. American drives on the right. British drives on the left.

  2. Maha Anna is right on this topic.

  3. I'll be right back.

  4. These are right angle triangles.

  5. You have the right to disagree with me.

  6. He is a right extremist.

  7. Actually, you can even overload the English word right to mean a dog in certain communication circle. Just thinking a scenario, you name your dog as Right, then in your family, when you or your kids talk about Right, the most of the time, it is referring to the dog. And it is a valid overloading; no body will put you in jail or even criticize you for your use of English word right this way...

  8. ...

The English word right is overloaded here. All natural languages are overloaded long before computer even invented. Polymorphism is a very specific OO concept, which has nothing to do with overloading. You really need to read a good OO book to understand it. It is too large a job for me to write about it here. There is so much misunderstanding out there on this topic, a lot of them are in published books. Like Marcus said: "Don't believe everything you read." If you don't believe what you read here by Roseanne, I'm OK.

P.S. The word Polymorphism itself in natural languages can be overloaded too like the Right example in English. You can overload the word polymorphism with whatever meaning you want it to mean. However, I still agree with most computer scientists' narrow and precise definition of polymorphism. If you don't agree with me, no more arguments are needed; we all can rest in peace...

9. When ambiguity exists between method calls, how does compiler resolve it? Why String version of the method is called instead of the Object version in the following example?

// Overloading.java
public class Overloading {

public void method(Object o) {
System.out.println("Object Version");
}

// String is an Object, but a specific Object
public void method(String s) {
System.out.println("String Version");
}

public static void main(String args[]) {
Overloading test = new Overloading();

// null is ambiguous to both methods
// The more specific one is called
test.method(null); // String Version
}
}

A:

The answer is in the comments of above code; just remember that when ambiguity exists between method calls, compiler resolves it by choosing the more specific ones. If it does not work, it will error out.

Why String is more specific than Object?

This is a Basic OO concept about generalization/specialization, read here for more specific information. Here is a brief:

OakTree is a specific Tree.
Cat is a specific Animal.
String is a specific Object.
Subclass ISA specific Baseclass.

10. Can overloaded methods have the same signature but different return type?

A: No, absolutely not!

In any programming languages, Methods overloading only applies to methods with different signatures. If same signature, there is only one method, two return types is impossible for one method. Try 5-10 line of code in Java or C++, you get your answer.Read here from JLS 8.4.7 Overloading


If two methods of a class (whether both declared in the same class, or both inherited by a class, or one declared and one inherited) have the same name but different signatures, then the method name is said to be overloaded. This fact causes no difficulty and never of itself results in a compile-time error. There is no required relationship between the return types or between the throws clauses of two methods with the same name but different signatures.


However, If we have two overloaded methods (which means they have the same name, but different signatures), they can have same/different return types, and/or throw same/different exceptions.

11. Can static method be overridden?

A: No!

The concept of overriding is binding at runtime, or polymorphism. Static is just on the opposite side of the equation, binding at the compile time, polymorphism does not apply to static method.


Methods a Subclass Cannot Override A subclass cannot override methods that are declared final in the superclass (by definition, final methods cannot be overridden). If you attempt to override a final method, the compiler displays an error message similar to the following and refuses to compile the program:"
... "Also, a subclass cannot override methods that are declared static in the superclass. In other words, a subclass cannot override a class method. A subclass can hide a static method in the superclass by declaring a static method in the subclass with the same signature as the static method in the superclass. " Quotation from Overriding Methods of The Java Tutorial


See more interesting discussion and sample code here: Can subclass override methods that are declared static in the superclass?

12. Can constructor be overridden?

A: No!

No, constructor cannot be overridden. Constructor must have the same name of the class itself, can never be its ancestor's name. For constructor calling orders, read here: What is the calling order of constructors along the hierarchy, from child up, or from ancestor down?

13. Can you explain the result of the following example? Oh, my!

class Base {
public boolean foo(Base b) {
return true;
}
}
class Sub extends Base {
public boolean foo(Sub s) {
return false;
}
}

public class Test {
public static void main(String argv[]) {
Base bb = new Base();
Base bs = new Sub();
Sub ss = new Sub();

System.out.println(bb.foo(bb)); //true

System.out.println(bs.foo(bs)); //true ???
System.out.println(bs.foo(ss)); //true ???
System.out.println(bs.foo(bb)); //true ???
System.out.println(ss.foo(bs)); //true ???
System.out.println(ss.foo(bb)); //true ???

System.out.println(ss.foo(ss)); //false
}
}

A: The foo methods are overloaded in the Sub. In Base, there is only one foo method, and it is not overridden by the Sub!

Overloading is fundamentally different then overriding. There is no polymorphism or dynamic binding here!!! All decisions are made at compile time!!! See detailed explanation in the same code below, documented!

class Base {
// There is only one foo method in Base!!!
public boolean foo(Base b) {
return true;
}
}
class Sub extends Base {
// differnt signature, method overloading
// there are 2 foo methods in the Sub
public boolean foo(Sub s) {
return false;
}
}

public class Test {
public static void main(String argv[]) {
// bb is a Base ref to the compiler, Base obj at runtime
Base bb = new Base();
// bs is a Base ref to the compiler, Sub obj at runtime
Base bs = new Sub();
// ss is a Sub ref to the compiler, Sub obj at runtime
Sub ss = new Sub();

// All these 4 lines are Base ref
// call Base.foo(Base) method, and only one foo available
// bs is a Base ref, and ss ISA Base ref too
// Everything is fine!!!
System.out.println(bb.foo(bb)); //true
System.out.println(bs.foo(bs)); //true
System.out.println(bs.foo(ss)); //true
System.out.println(bs.foo(bb)); //true

// bb, bs are both Base refs to Compiler
// ss is a Sub ref
// call Sub.foo(Base) which is inherited from Base
System.out.println(ss.foo(bs)); //true
System.out.println(ss.foo(bb)); //true

// no doubt about this one, am I right?
System.out.println(ss.foo(ss)); //false
}
}

Are Java and C++ using the same rules on method overriding/overloading?

14. Are Java and C++ using the same rules on method overriding/overloading?

A: Yes, they are basically the same.

Here are two equivalent class A/B in Java and C++. Compare carefully!

A.java

public class A {
public int mtdA(int x) {
return x + 3;
}
public int mtdB(int x, int y) {
return x + y;
}
}

class B extends A {
/*
$ javac A.java
A.java:23: mtdA(int) in B cannot override mtdA(int) in A;
attempting to use incompatible return type

found : double
required: int
public double mtdA(int x) {
^
1 error

public double mtdA(int x) {
return x + 0.2;
}
*/

// Compiled OK
public double mtdB(int x) {
return x + 0.2;
}
}

A.cpp

class A {
virtual int mtdA(int x) {
return x + 3;
};
virtual int mtdB(int x, int y) {
return x + y;
};
};

class B : public A {
// $ g++ A.cpp
// A.cpp:15: error: conflicting return type specified for `virtual double B::mtdA(int)'
// A.cpp:2: error: overriding `virtual int A::mtdA(int)'
/*
virtual double mtdA(int x) {
return x + 0.2;
};
*/


// OK
virtual double mtdB(int x) {
return x + 0.2;
};
};

No comments: