Thinking in Java - 4th Edition
1079 pág.

Thinking in Java - 4th Edition


DisciplinaProgramação Orientada A Objetos4.354 materiais61.248 seguidores
Pré-visualização50 páginas
(1) Add an overloaded constructor to the previous exercise that takes a 
String argument and prints it along with your message. 
Exercise 5: (2) Create a class called Dog with an overloaded bark( ) method. This 
method should be overloaded based on various primitive data types, and print different types 
of barking, howling, etc., depending on which overloaded version is called. Write a main( ) 
that calls all the different versions. 
Exercise 6: (1) Modify the previous exercise so that two of the overloaded methods have 
two arguments (of two different types), but in reversed order relative to each other. Verify 
that this works. 
Exercise 7: (1) Create a class without a constructor, and then create an object of that 
class in main( ) to verify that the default constructor is automatically synthesized. 
Initialization & Cleanup 115 
116 Thinking in Java Bruce Eckel 
The this keyword 
If you have two objects of the same type called a and b, you might wonder how it is that you 
can call a method peel( ) for both those objects: 
//: initialization/BananaPeel.java 
 
class Banana { void peel(int i) { /* ... */ } } 
 
public class BananaPeel { 
 public static void main(String[] args) { 
 Banana a = new Banana(), 
 b = new Banana(); 
 a.peel(1); 
 b.peel(2); 
 } 
} ///:~ 
If there\u2019s only one method called peel( ), how can that method know whether it\u2019s being 
called for the object a or b? 
To allow you to write the code in a convenient object-oriented syntax in which you \u201csend a 
message to an object,\u201d the compiler does some undercover work for you. There\u2019s a secret first 
argument passed to the method peel( ), and that argument is the reference to the object 
that\u2019s being manipulated. So the two method calls become something like: 
Banana.peel(a, 1); 
Banana.peel(b, 2); 
This is internal and you can\u2019t write these expressions and get the compiler to accept them, 
but it gives you an idea of what\u2019s happening. 
Suppose you\u2019re inside a method and you\u2019d like to get the reference to the current object. 
Since that reference is passed secretly by the compiler, there\u2019s no identifier for it. However, 
for this purpose there\u2019s a keyword: this. The this keyword\u2014which can be used only inside a 
non-static method\u2014produces the reference to the object that the method has been called 
for. You can treat the reference just like any other object reference. Keep in mind that if 
you\u2019re calling a method of your class from within another method of your class, you don\u2019t 
need to use this. You simply call the method. The current this reference is automatically 
used for the other method. Thus you can say: 
//: initialization/Apricot.java 
public class Apricot { 
 void pick() { /* ... */ } 
 void pit() { pick(); /* ... */ } 
} ///:~ 
Inside pit( ), you could say this.pick( ) but there\u2019s no need to.1
 
The compiler does it for you 
automatically. The this keyword is used only for those special cases in which you need to 
explicitly use the reference to the current object. For example, it\u2019s often used in return 
statements when you want to return the reference to the current object: 
                                                            
1 Some people will obsessively put this in front of every method call and field reference, arguing that it makes it \u201cclearer 
and more explicit.\u201d Don\u2019t do it. There\u2019s a reason that we use high-level languages: They do things for us. If you put this in 
when it\u2019s not necessary, you will confuse and annoy everyone who reads your code, since all the rest of the code they\u2019ve 
read won\u2019t use this everywhere. People expect this to be used only when it is necessary. Following a consistent and 
straightforward coding style saves time and money. 
//: initialization/Leaf.java 
// Simple use of the "this" keyword. 
 
public class Leaf { 
 int i = 0; 
 Leaf increment() { 
 i++; 
 return this; 
 } 
 void print() { 
 System.out.println("i = " + i); 
 } 
 public static void main(String[] args) { 
 Leaf x = new Leaf(); 
 x.increment().increment().increment().print(); 
 } 
} /* Output: 
i = 3 
*///:~ 
Because increment( ) returns the reference to the current object via the this keyword, 
multiple operations can easily be performed on the same object. 
The this keyword is also useful for passing the current object to another method: 
//: initialization/PassingThis.java 
 
class Person { 
 public void eat(Apple apple) { 
 Apple peeled = apple.getPeeled(); 
 System.out.println("Yummy"); 
 } 
} 
 
class Peeler { 
 static Apple peel(Apple apple) { 
 // ... remove peel 
 return apple; // Peeled 
 } 
} 
 
class Apple { 
 Apple getPeeled() { return Peeler.peel(this); } 
} 
 
public class PassingThis { 
 public static void main(String[] args) { 
 new Person().eat(new Apple()); 
 } 
} /* Output: 
Yummy 
*///:~ 
Apple needs to call Peeler.peel( ), which is a foreign utility method that performs an 
operation that, for some reason, needs to be external to Apple (perhaps the external method 
can be applied across many different classes, and you don\u2019t want to repeat the code). To pass 
itself to the foreign method, it must use this. 
Exercise 8: (1) Create a class with two methods. Within the first method, call the second 
method twice: the first time without using this, and the second time using this\u2014just to see it 
working; you should not use this form in practice. 
Initialization & Cleanup 117 
Calling constructors from constructors 
When you write several constructors for a class, there are times when you\u2019d like to call one 
constructor from another to avoid duplicating code. You can make such a call by using the 
this keyword. 
Normally, when you say this, it is in the sense of \u201cthis object\u201d or \u201cthe current object,\u201d and by 
itself it produces the reference to the current object. In a constructor, the this keyword takes 
on a different meaning when you give it an argument list. It makes an explicit call to the 
constructor that matches that argument list. Thus you have a straightforward way to call 
other constructors: 
//: initialization/Flower.java 
// Calling constructors with "this" 
import static net.mindview.util.Print.*; 
 
public class Flower { 
 int petalCount = 0; 
 String s = "initial value"; 
 Flower(int petals) { 
 petalCount = petals; 
 print("Constructor w/ int arg only, petalCount= " 
 + petalCount); 
 } 
 Flower(String ss) { 
 print("Constructor w/ String arg only, s = " + ss); 
 s = ss; 
 } 
 Flower(String s, int petals) { 
 this(petals); 
//! this(s); // Can\u2019t call two! 
 this.s = s; // Another use of "this" 
 print("String & int args"); 
 } 
 Flower() { 
 this("hi", 47); 
 print("default constructor (no args)"); 
 } 
 void printPetalCount() { 
//! this(11); // Not inside non-constructor! 
 print("petalCount = " + petalCount + " s = "+ s); 
 } 
 public static void main(String[] args) { 
 Flower x = new Flower(); 
 x.printPetalCount(); 
 } 
} /* Output: 
Constructor w/ int arg only, petalCount= 47 
String & int args 
default constructor (no args) 
petalCount = 47 s = hi 
*///:~ 
The constructor Flower(String s, int petals) shows that, while you can call one 
constructor using this, you cannot call two. In addition, the constructor call must be the first 
thing you do, or you\u2019ll get a compiler error message. 
This example also shows another way you\u2019ll see this used. Since the name of the argument s 
and the name of the member data s are the same, there\u2019s an ambiguity. You can resolve it 
118 Thinking in Java Bruce Eckel 
Initialization & Cleanup 119 
using this.s, to say that you\u2019re referring to the member data. You\u2019ll often see this form used 
in Java code, and it\u2019s used in numerous places in this book. 
In printPetalCount( ) you can see that the compiler won\u2019t let you call a constructor from 
inside any method other than a constructor. 
Exercise 9: (1) Create a class with two (overloaded) constructors.