Let us quickly review whatever we learnt about Design Patterns in the previous few chapters
• A design pattern describes a proven solution to a recurring design problem, placing particular emphasis on the context and forces surrounding the problem, and the consequences and impact of the solution
• There are 5 design patterns in the SCWCD Exam:
o Value Object Pattern
o Data Access Object Pattern
o Business Delegate Pattern
o Model View Controller Pattern &
o Front Controller Pattern
• The Value Object pattern provides the best way to exchange data across tiers or system boundaries, especially when there is network communication involved. This is a pattern that solves performance issues around network latency
• The DAO pattern provides the connection between the business logic tier and the resource (usually a database) tier. The Data Access Object represents a general interface to the resources layer: It handles all calls to it. JDBC is the most commonly used example of this
• The Business Delegate pattern reduces the dependency between tiers. It is an attempt to make tiers interchangeable so one can access or utilize the services of any other
• The Model-View-Controller architecture compartmentalizes the data and business logic (model) from the presentation (view) from the user action interpreter (controller).
• The Front Controller pattern presents one entry point to a Web site or service. It provides a centralized entry point that controls and manages Web request handling. It eliminates the dependency of the user on a direct resource.
The Key Terms we learnt in the previous few chapters are:
• Design Patterns
• Model-View-Controller
• Value Object
• Data Access Object
• Front Controller
• Business Delegate
Previous Chapter: Chapter 58 - Other Design Patterns
Next Chapter: Self Test - Chapters 51 to 58
Topics Covered in the Blog - Synopsis
Showing posts with label quick recap. Show all posts
Showing posts with label quick recap. Show all posts
Friday, April 29, 2011
Quick Recap: Chapters 47 to 50
Let us quickly review what we learnt about the Web Application Deployment and the Deployment Descriptor web.xml in the previous few chapters.
Web Application Folder Structure:
1. The WEB-INF is the root directory of any Web Application
2. This directory contains two folders /classes – to hold all the class files and /lib to hold all the JAR files
3. The web.xml file also resides in WEB-INF Folder
Elements of a Deployment Descriptor:
The deployment descriptor has 77 elements but the most important ones are:
1. C = < context-param >
2. L = < listener >
3. S = < servlet >
4. S = < servlet-mapping >
5. S = < session-config >
6. W = < welcome-file-list >
7. E = < error-page >
8. T = < taglib >
9. S = < security-constraint >
10. L = < login-config >
11. S = < security-role >
Exception Handling:
You can specify the exception handling declaratively in the deployment descriptor. You do this with the error-page element and the exception-type subelement like so:
< web-app >
< error-page >
< exception-type > javax.servlet.ServletException < / exception-type >
< location > /servlet/ErrorDisplay < / location >
< / error-page >
< / web-app >
Application Security:
• Application Security is an important aspect of any web application. Our application should be prepared to handle atleast a minimum level of attack.
• Authentication is the process by which the system verifies if a user is who he really says he is
• Authorization is the process by which we place access control restrictions on the various resources of the system
• Authentication can be of 4 types:
o HTTP Basic Authentication
o HTTP Digest Authentication
o HTTPS Client Authentication &
o Form Based Authentication
Key Terms we learnt in these chapters are:
• Web application
• Web archive file
• WebApp deployment descriptor
• Authentication, authorization
• Security constraint
Previous Chapter: Chapter 50 - Web Application Security
Next Chapter: Self Test - Chapters 47 to 50
Web Application Folder Structure:
1. The WEB-INF is the root directory of any Web Application
2. This directory contains two folders /classes – to hold all the class files and /lib to hold all the JAR files
3. The web.xml file also resides in WEB-INF Folder
Elements of a Deployment Descriptor:
The deployment descriptor has 77 elements but the most important ones are:
1. C = < context-param >
2. L = < listener >
3. S = < servlet >
4. S = < servlet-mapping >
5. S = < session-config >
6. W = < welcome-file-list >
7. E = < error-page >
8. T = < taglib >
9. S = < security-constraint >
10. L = < login-config >
11. S = < security-role >
Exception Handling:
You can specify the exception handling declaratively in the deployment descriptor. You do this with the error-page element and the exception-type subelement like so:
< web-app >
< error-page >
< exception-type > javax.servlet.ServletException < / exception-type >
< location > /servlet/ErrorDisplay < / location >
< / error-page >
< / web-app >
Application Security:
• Application Security is an important aspect of any web application. Our application should be prepared to handle atleast a minimum level of attack.
• Authentication is the process by which the system verifies if a user is who he really says he is
• Authorization is the process by which we place access control restrictions on the various resources of the system
• Authentication can be of 4 types:
o HTTP Basic Authentication
o HTTP Digest Authentication
o HTTPS Client Authentication &
o Form Based Authentication
Key Terms we learnt in these chapters are:
• Web application
• Web archive file
• WebApp deployment descriptor
• Authentication, authorization
• Security constraint
Previous Chapter: Chapter 50 - Web Application Security
Next Chapter: Self Test - Chapters 47 to 50
Labels:
authentication,
authorization,
deployment of web application,
getting scwcd certified,
quick recap,
quick review,
scwcd certification
| Reactions: |
Thursday, April 28, 2011
Quick Recap: Chapters 44 & 45
Now, let us quickly review what we have learnt about Tag Libraries and Custom Tags in the previous two chapters.
Tag Libraries:
• A tag library is similar to JavaBeans, which means that you can reference a class from JSP using XML notation.
• A tag library maps XML tags to underlying class methods in a Tag Library Descriptor (.tld) file
• JavaBeans allow you to separate your applications into presentation code (contained in the JSP) and business logic (contained in the beans). JavaBeans is a good start, but doesn't take us too far. If we want to do stuff, beyond getting and setting values, we need to use custom tags. Because this need made its way into Sun's Java wish list, we now have custom tags
• The main reasons as to why Tag Libraries are used so commonly are: Simple, Portable, Flexible, Expressive and Reusable
• Steps to create a tag library are:
o Write and compile a simple tag handler that services the custom tag in your JSP (JSP custom tag attribute invokes a setter method in tag handler). Place the tag handler Java class files for your tags in the WEB-INF/classes directory of your Web application.
o Write the tag library descriptor (TLD), which defines the tag library including the name of the tag handler class and attributes. Place it in its directory, which you declare in the deployment descriptor (CATALINA_HOME/webapps/examples/WEB-INF/xyz.tld).
o Declare the Tag Library Descriptor in the Web application deployment descriptor (CATALINA_HOME/webapps/examples/WEB-INF/web.xml)
o Declare the tag library in your JSP source using the JSP directive.
o Use the custom tag in your JSP page.
o Restart your container and test your tag library.
Custom Tags:
• The custom tag is a convention that allows you to have the container call the tag library life cycle event methods (for example, doStartTag), including the attribute get/set calls automatically invoked when attributes are declared in the custom tag. doStartTag and doEndTag methods are called when the JSP page request is processed
• A Custom tag has 3 attributes:
o Name
o Required and
o Rtexprval
• A Custom Tag body can be:
o Empty
o Custom Tag that surrounds JSP code
o Custom tag that surrounds contents that is used only by the tag handler.
• The various Events of a Custom Tag are:
o EVAL_BODY_INCLUDE – Evaluate body into existing output stream
o EVAL_BODY_AGAIN – Evaluate body again
o EVAL_PAGE – Continue Evaluating the Page
o SKIP_BODY – Skip body Evaluation. Stop processing the JSP after the current custom tag
o SKIP_PAGE – Stop processing the JSP after the current custom tag.
The Key Terms we learnt in these chapters are:
• Custom tags
• Tag libraries
• Tag Library Descriptor
• Web Deployment Descriptor
• Nested tags
• Tag attributes and bodies
• Taglib directive
• doStartTag()
• doEndTag()
Previous Chapter: Chapter 45 - Custom Tags
Next chapter: Self Test - Chapters 44 & 45
Tag Libraries:
• A tag library is similar to JavaBeans, which means that you can reference a class from JSP using XML notation.
• A tag library maps XML tags to underlying class methods in a Tag Library Descriptor (.tld) file
• JavaBeans allow you to separate your applications into presentation code (contained in the JSP) and business logic (contained in the beans). JavaBeans is a good start, but doesn't take us too far. If we want to do stuff, beyond getting and setting values, we need to use custom tags. Because this need made its way into Sun's Java wish list, we now have custom tags
• The main reasons as to why Tag Libraries are used so commonly are: Simple, Portable, Flexible, Expressive and Reusable
• Steps to create a tag library are:
o Write and compile a simple tag handler that services the custom tag in your JSP (JSP custom tag attribute invokes a setter method in tag handler). Place the tag handler Java class files for your tags in the WEB-INF/classes directory of your Web application.
o Write the tag library descriptor (TLD), which defines the tag library including the name of the tag handler class and attributes. Place it in its directory, which you declare in the deployment descriptor (CATALINA_HOME/webapps/examples/WEB-INF/xyz.tld).
o Declare the Tag Library Descriptor in the Web application deployment descriptor (CATALINA_HOME/webapps/examples/WEB-INF/web.xml)
o Declare the tag library in your JSP source using the JSP
o Use the custom tag in your JSP page.
o Restart your container and test your tag library.
Custom Tags:
• The custom tag is a convention that allows you to have the container call the tag library life cycle event methods (for example, doStartTag), including the attribute get/set calls automatically invoked when attributes are declared in the custom tag. doStartTag and doEndTag methods are called when the JSP page request is processed
• A Custom tag has 3 attributes:
o Name
o Required and
o Rtexprval
• A Custom Tag body can be:
o Empty
o Custom Tag that surrounds JSP code
o Custom tag that surrounds contents that is used only by the tag handler.
• The various Events of a Custom Tag are:
o EVAL_BODY_INCLUDE – Evaluate body into existing output stream
o EVAL_BODY_AGAIN – Evaluate body again
o EVAL_PAGE – Continue Evaluating the Page
o SKIP_BODY – Skip body Evaluation. Stop processing the JSP after the current custom tag
o SKIP_PAGE – Stop processing the JSP after the current custom tag.
The Key Terms we learnt in these chapters are:
• Custom tags
• Tag libraries
• Tag Library Descriptor
• Web Deployment Descriptor
• Nested tags
• Tag attributes and bodies
• Taglib directive
• doStartTag()
• doEndTag()
Previous Chapter: Chapter 45 - Custom Tags
Next chapter: Self Test - Chapters 44 & 45
Labels:
custom tag library,
custom taglibs,
jsp taglib,
jsp tag libraries,
jsp tag library,
quick recap,
tag-lib,
taglibs
| Reactions: |
Wednesday, March 23, 2011
Quick Recap: Chapters 6 to 19
Let us quickly go through what we learnt in the previous chapters…
Request Handling Basics:
• The HTTP methods GET, POST, and PUT are how browsers and Web servers trade data with each other
• The GET retrieves a page without providing much information, while a POST can package huge amounts of information with its request
• The most important objects in the servlet process are the request and response objects
• The request parameters for the servlet are the strings sent by the client to the Servlet Container. The container parses the request and puts the information in a HttpServletRequest object which is passed to the servlet
• The container wraps the response parameters with the HttpServletResponse object which is passed back to the container
Scope:
• When something has Context scope it is application-wide and all users can share data
• Session scope means one user can share data across page views, but other users can't
• Request scope restricts data to only that page
Servlet Lifecycle:
• The init() method is used to initialize the Servlet
• The service() methods (doGet(), doPost() etc) get invoked everytime a user request gets submitted
• The destroy() method is used to kill/invalidate the Servlet once it is no longer required.
Key Terms we Learnt:
The key terms we learnt and understood in these chapters were:
1. Redirection
2. Servlet Life-Cycle
3. Servlet Forwarding and Includes
4. Servlet attribute
5. Context parameters
6. Application session
7. listeners
Previous Chapter: Chapter 19 - Listeners & Interfaces in the Web Context
Next Chapter: Self Test - Chapters 6 to 19
Request Handling Basics:
• The HTTP methods GET, POST, and PUT are how browsers and Web servers trade data with each other
• The GET retrieves a page without providing much information, while a POST can package huge amounts of information with its request
• The most important objects in the servlet process are the request and response objects
• The request parameters for the servlet are the strings sent by the client to the Servlet Container. The container parses the request and puts the information in a HttpServletRequest object which is passed to the servlet
• The container wraps the response parameters with the HttpServletResponse object which is passed back to the container
Scope:
• When something has Context scope it is application-wide and all users can share data
• Session scope means one user can share data across page views, but other users can't
• Request scope restricts data to only that page
Servlet Lifecycle:
• The init() method is used to initialize the Servlet
• The service() methods (doGet(), doPost() etc) get invoked everytime a user request gets submitted
• The destroy() method is used to kill/invalidate the Servlet once it is no longer required.
Key Terms we Learnt:
The key terms we learnt and understood in these chapters were:
1. Redirection
2. Servlet Life-Cycle
3. Servlet Forwarding and Includes
4. Servlet attribute
5. Context parameters
6. Application session
7. listeners
Previous Chapter: Chapter 19 - Listeners & Interfaces in the Web Context
Next Chapter: Self Test - Chapters 6 to 19
Tuesday, March 1, 2011
Quick Recap: Chapters 1 to 5
Let us quickly go over the concepts we have covered in the past few chapters.
JSP & Servlet History
• ARPANET was the initial backbone based on which Internet was built
• Tim Berners Lee paved the way for the current day Internet and World Wide Web
• CGI helped people transfer data from one computer to another
• Because CGI was not scalable, people looked out for better alternatives
• JSP and Servlets became an easier and a more scalable alternative to CGI
Advantages of Using Servlets
a. They are faster than CGI scripts because each CGI script produces an entirely new process that takes a lot of time to execute, whereas a servlet creates only a new thread.
b. Servlet API is standard and available easily on the internet (like JSPs)
c. Servlets have the advantages like ease of development & platform independence (like Java)
d. They can access all the J2SE and J2EE APIs
e. Can take the full advantage & capabilities of the Java programming language
Advantages of Using JSPs
a. Write Once, Run Anywhere
b. Code Re-use
c. Support for Scripting
d. Supports Actions
e. Supports both Static & Dynamic Content
f. Supports N-tier Enterprise Application Architecture
g. Superior Quality Documentation & Examples (All over the internet)
h. Reusable Tag Libraries
Web Servers & Servlet Containers
• A web server is the server on which our J2EE application runs
• A Servlet container is similar to a JVM for java programs and executes our Servlets
• Data is transferred using the request/response model
JSP to Servlet Conversion
• A JSP file gets converted into a Servlet at run time
• The web server (Ex: Tomcat) does the conversion of the JSP
• The web server invokes the converted Servlet version of the JSP page, every time the JSP is invoked.
Previous Chapter: Chapter 5 - JSP to Servlet Conversion
Next Chapter: Self Test - Chapters 1 to 5
JSP & Servlet History
• ARPANET was the initial backbone based on which Internet was built
• Tim Berners Lee paved the way for the current day Internet and World Wide Web
• CGI helped people transfer data from one computer to another
• Because CGI was not scalable, people looked out for better alternatives
• JSP and Servlets became an easier and a more scalable alternative to CGI
Advantages of Using Servlets
a. They are faster than CGI scripts because each CGI script produces an entirely new process that takes a lot of time to execute, whereas a servlet creates only a new thread.
b. Servlet API is standard and available easily on the internet (like JSPs)
c. Servlets have the advantages like ease of development & platform independence (like Java)
d. They can access all the J2SE and J2EE APIs
e. Can take the full advantage & capabilities of the Java programming language
Advantages of Using JSPs
a. Write Once, Run Anywhere
b. Code Re-use
c. Support for Scripting
d. Supports Actions
e. Supports both Static & Dynamic Content
f. Supports N-tier Enterprise Application Architecture
g. Superior Quality Documentation & Examples (All over the internet)
h. Reusable Tag Libraries
Web Servers & Servlet Containers
• A web server is the server on which our J2EE application runs
• A Servlet container is similar to a JVM for java programs and executes our Servlets
• Data is transferred using the request/response model
JSP to Servlet Conversion
• A JSP file gets converted into a Servlet at run time
• The web server (Ex: Tomcat) does the conversion of the JSP
• The web server invokes the converted Servlet version of the JSP page, every time the JSP is invoked.
Previous Chapter: Chapter 5 - JSP to Servlet Conversion
Next Chapter: Self Test - Chapters 1 to 5
Labels:
arpanet,
internet history,
j2ee history,
jsp,
jsp and servlets,
quick recap,
quick review,
scwcd,
scwcd certification,
scwcd exam,
servlets,
servlets and jsps
| Reactions: |
Saturday, February 26, 2011
Self Test: Chapters 55 to 61
This is going to be the last self test chapter in our SCJP Exam series. The following questions will help you judge your expertise about threads that you learnt just now.
Questions:
Question 1
The following block of code creates a Thread using a Runnable target:
Runnable r = new MyRunnable();
Thread SimpleThreadExample = new Thread(r);
Which of the following classes can be used to create the target, so that the preceding code compiles correctly?
A. public class MyRunnable extends Runnable{public void run(){}}
B. public class MyRunnable extends Object{public void run(){}}
C. public class MyRunnable implements Runnable{public void run(){}}
D. public class MyRunnable implements Runnable{void run(){}}
E. public class MyRunnable implements Runnable{public void start(){}}
Question 2
Given:
3. class SimpleThreadExample extends Thread {
4. public static void main(String [] args) {
5. SimpleThreadExample t = new SimpleThreadExample();
6. Thread x = new Thread(t);
7. x.start();
8. }
9. public void run() {
10. for(int i=0;i<3;++i) {
11. System.out.print(i + "..");
12. }
13. }
14. }
What is the result of this code?
A. Compilation fails
B. 1..2..3..
C. 0..1..2..3..
D. 0..1..2..
E. An exception occurs at runtime
Question 3
Given:
3. class Test {
4. public static void main(String [] args) {
5. printStuff(args);
6. }
7. public static void printStuff(String[] lines) {
8. for(int i=0;i < lines.length;i++){
9. System.out.println(lines[i]);
10. Thread.currentThread().sleep(1000);
11. }
12. }
13. }
The static method Thread.currentThread() returns a reference to the currently executing Thread object. What is the result of this code?
A. Each String in the array lines will output, with a 1-second pause between lines
B. Each String in the array lines will output, with no pause in between because this method is not executed in a Thread
C. Each String in the array lines will output, and there is no guarantee there will be a pause because currentThread() may not retrieve this thread
D. This code will not compile
E. Each String in the lines array will print, with at least a one-second pause between lines
Question 4
Assume you have a class that holds two private variables: x and y. Which of the following pairs can prevent concurrent access problems in that class? (Choose all that apply.)
A. public int read(){return x+y;}
B. public void set(int x, int y){this.x=x;this.y=y;}
C. public synchronized int read(){return x+y;}
D. public synchronized void set(int x, int y){this.x=x;this.y=y;}
E. public int read(){synchronized(x){return x+y;}}
F. public void set(int x, int y){synchronized(x){this.x=x;this.y=y;}}
G. public int read(){synchronized(x){return x+y;}}
H. public void set(int x, int y){synchronized(y){this.x=x;this.y=y;}}
I. public synchronized(this) int read(){return x+y;}
J. public synchronized(this) void set(int x, int y){this.x=x;this.y=y;}
K. public int read(){synchronized(this){return x+y;}}
L. public void set(int x, int y){synchronized(this){this.x=x;this.y=y;}}
Question 5
Given:
1. public class TestWaitMethod {
2. public static void main(String [] args) {
3. System.out.print("1 ");
4. synchronized(args){
5. System.out.print("2 ");
6. try {
7. args.wait();
8. }
9. catch(InterruptedException e){}
10. }
11. System.out.print("3 ");
12. }
13. }
What is the result of trying to compile and run this program?
A. It fails to compile because the IllegalMonitorStateException of wait() is not dealt with in line 7
B. 1 2 3
C. 1 3
D. 1 2
E. At runtime, it throws an IllegalMonitorStateException when trying to wait
F. It will fail to compile because it has to be synchronized on the this object
Question 6
Assume the following method is properly synchronized and called from a thread A on an object B:
wait(2000);
After calling this method, when will the thread A become a candidate to get another turn at the CPU?
A. After object B is notified, or after two seconds
B. After the lock on B is released, or after two seconds
C. Two seconds after object B is notified
D. Two seconds after lock B is released
Question 7
Which are true? (Choose all that apply.)
A. The notifyAll() method must be called from a synchronized context
B. To call wait(), an object must own the lock on the thread
C. The notify() method is defined in class java.lang.Thread
D. When a thread is waiting as a result of wait(), it releases its lock
E. The notify() method causes a thread to immediately release its lock
F. The difference between notify() and notifyAll() is that notifyAll() notifies all waiting threads, regardless of the object they’re waiting on
Question 8
Given the scenario: This class is intended to allow users to write a series of messages, so that each message is identified with a timestamp and the name of the thread that wrote the message:
public class MyErrorLoggingUtilClass {
private StringBuilder contents = new StringBuilder();
public void log(String message) {
contents.append(System.currentTimeMillis());
contents.append(": ");
contents.append(Thread.currentThread().getName());
contents.append(message);
contents.append("\n");
}
public String getLogMessages() { return contents.toString(); }
}
How can we ensure that instances of this class can be safely used by multiple threads?
A. This class is already thread-safe
B. Replacing StringBuilder with StringBuffer will make this class thread-safe
C. Synchronize the log() method only
D. Synchronize the getLogMessages() method only
E. Synchronize both log() and getLogMessages()
F. This class cannot be made thread-safe
Question 9
Given:
public static synchronized void main(String[] args) throws
InterruptedException {
Thread t = new Thread();
t.start();
System.out.print("X");
t.wait(10000);
System.out.print("Y");
}
What is the result of this code?
A. It prints X and exits
B. It prints X and never exits
C. It prints XY and exits almost immeditately
D. It prints XY with a 10-second delay between X and Y
E. It prints XY with a 10000-second delay between X and Y
F. The code does not compile
G. An exception is thrown at runtime
Question 10
Given:
class SimpleThreadExample extends Thread {
SimpleThreadExample() {
System.out.print(" SimpleThreadExample");
}
public void run() {
System.out.print(" aaa");
}
public void run(String s) {
System.out.print(" bbb");
}
}
public class TestThreads {
public static void main (String [] args) {
Thread t = new SimpleThreadExample() {
public void run() {
System.out.print(" ccc");
}
};
t.start();
} }
What is the result?
A. ccc
B. SimpleThreadExample ccc
C. SimpleThreadExample aaa
D. ccc aaa
E. ccc aaa bbb
F. aaa ccc
G. Compilation fails
H. An exception is thrown at runtime
Question 11
Given:
public class ExampleThread {
synchronized void a() { doSomething(); }
static synchronized void b() { doSomething(); }
static void doSomething() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
public static void main(String[] args) {
final ExampleThread x = new ExampleThread();
final ExampleThread y = new ExampleThread();
Runnable runnable = new Runnable() {
public void run() {
int option = (int) (Math.random() * 4);
switch (option) {
case 0: x.a(); break;
case 1: x.b(); break;
case 2: y.a(); break;
case 3: y.b(); break;
}
}
};
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
thread1.start();
thread2.start();
}
}
Which of the following pairs of method invocations could NEVER be executing at the same time? (Choose all that apply.)
A. x.a() in thread1, and x.a() in thread2
B. x.a() in thread1, and x.b() in thread2
C. x.a() in thread1, and y.a() in thread2
D. x.a() in thread1, and y.b() in thread2
E. x.b() in thread1, and x.a() in thread2
F. x.b() in thread1, and x.b() in thread2
G. x.b() in thread1, and y.a() in thread2
H. x.b() in thread1, and y.b() in thread2
Question 12
Given:
public class MultipleThreadExample {
static Thread cena, orton;
public static void main(String[] args) {
cena = new Thread() {
public void run() {
System.out.println("A");
try {
orton.sleep(1000);
} catch (Exception e) {
System.out.println("B");
}
System.out.println("C");
}
};
orton = new Thread() {
public void run() {
System.out.println("D");
try {
cena.wait();
} catch (Exception e) {
System.out.println("E");
}
System.out.println("F");
}
};
cena.start();
orton.start();
}
}
Which letters will eventually appear somewhere in the output? (Choose all that apply.)
A. A
B. B
C. C
D. D
E. E
F. F
G. The answer cannot be reliably determined
H. The code does not compile
Question 13
Given:
3. public class Runner implements Runnable {
4. void go(long id) {
5. System.out.println(id);
6. }
7. public static void main(String[] args) {
8. System.out.print(Thread.currentThread().getId() + " ");
9. // insert code here
10. }
11. public void run() { go(Thread.currentThread().getId()); }
12. }
And given the following five fragments:
I. new Runner().run();
II. new Runner().start();
III. new Thread(new Runner());
IV. new Thread(new Runner()).run();
V. new Thread(new Runner()).start();
When the five fragments are inserted, one at a time at line 9, which are true? (Choose all that apply.)
A. All five will compile
B. Only one might produce the output 4 4
C. Only one might produce the output 4 2
D. Exactly two might produce the output 4 4
E. Exactly two might produce the output 4 2
F. Exactly three might produce the output 4 4
G. Exactly three might produce the output 4 2
Question 14
Given:
3. public class Awesome implements Runnable {
4. public static void main(String[] args) {
5. Thread t = new Thread(new Awesome());
6. t.start();
7. System.out.print("a1 ");
8. t.join();
9. System.out.print("a2 ");
10. }
11. public void run() {
12. System.out.print("b1 ");
13. System.out.print("b2 ");
14. }
15. }
Which are true? (Choose all that apply.)
A. Compilation fails
B. The output could be b1 b2 a1 a2
C. The output could be a1 a2 b1 b2
D. The output could be a1 b1 b2 a2
E. The output could be a1 b1 a2 b2
F. An exception is thrown at runtime
Question 15
Given:
3. class Friends {
4. static long flag = 0;
5. // insert code here
6. if(flag == 0) flag = id;
7. for(int x = 1; x < 3; x++) {
8. if(flag == id) System.out.print("yo ");
9. else System.out.print("Friend ");
10. }
11. }
12. }
13. public class FriendsHangOut implements Runnable {
14. static Friends d;
15. public static void main(String[] args) {
16. new FriendsHangOut().go();
17. }
18. void go() {
19. d = new Friends();
20. new Thread(new FriendsHangOut()).start();
21. new Thread(new FriendsHangOut()).start();
22. }
23. public void run() {
24. d.chat(Thread.currentThread().getId());
25. }
26. }
And given these two fragments:
I. synchronized void chat(long id) {
II. void chat(long id) {
When fragment I or fragment II is inserted at line 5, which are true? (Choose all that apply.)
A. An exception is thrown at runtime
B. With fragment I, compilation fails
C. With fragment II, compilation fails
D. With fragment I, the output could be yo Friend Friend yo
E. With fragment I, the output could be Friend Friend yo yo
F. With fragment II, the output could be yo Friend Friend yo
Answers:
Answer 1
C is correct. The class implements the Runnable interface with a legal run() method.
A is incorrect because interfaces are implemented, not extended. B is incorrect because even though the class has a valid public void run() method, it does not implement the Runnable interface. D is incorrect because the run() method must be public. E is incorrect because the method to implement is run(), not start().
Answer 2
D is correct. The thread SimpleThreadExample will start and loop three times (from 0 to 2).
A is incorrect because the Thread class implements the Runnable interface; therefore, in line 5, Thread can take an object of type Thread as an argument in the constructor (this is NOT recommended). B and C are incorrect because the variable i in the for loop starts with a value of 0 and ends with a value of 2.
Answer 3
D is correct. The sleep() method must be enclosed in a try/catch block, or the method printStuff() must declare it throws the InterruptedException.
E is incorrect, but it would be correct if the InterruptedException was dealt with (A is too precise). B is incorrect (even if the InterruptedException was dealt with) because all Java code, including the main() method, runs in threads. C is incorrect. The sleep() method is static, it always affects the currently executing thread.
Answer 4
B and F are correct. By marking the methods as synchronized, the threads will get the lock of the this object before proceeding. Only one thread will be setting or reading at any given moment, thereby assuring that read() always returns the addition of a valid pair.
A is incorrect because it is not synchronized; therefore, there is no guarantee that the values added by the read() method belong to the same pair. C and D are incorrect; only objects can be used to synchronize on. E fails—it is not possible to select other objects (even this) to synchronize on when declaring a method as synchronized.
Answer 5
D is correct. 1 and 2 will be printed, but there will be no return from the wait call because no other thread will notify the main thread, so 3 will never be printed. It’s frozen at line 7.
A is incorrect; IllegalMonitorStateException is an unchecked exception. B and C are incorrect; 3 will never be printed, since this program will wait forever. E is incorrect because IllegalMonitorStateException will never be thrown because the wait() is done on args within a block of code synchronized on args. F is incorrect because any object can be used to synchronize on and this and static don’t mix.
Answer 6
A is correct. Either of the two events will make the thread a candidate for running again.
B is incorrect because a waiting thread will not return to runnable when the lock is released, unless a notification occurs. C is incorrect because the thread will become a candidate immediately after notification. D is also incorrect because a thread will not come out of a waiting pool just because a lock has been released.
Answer 7
A is correct because notifyAll() (and wait() and notify()) must be called from within a synchronized context. D is a correct statement.
B is incorrect because to call wait(), the thread must own the lock on the object that wait() is being invoked on, not the other way around. C is wrong because notify() is defined in java.lang.Object. E is wrong because notify() will not cause a thread to release its locks. The thread can only release its locks by exiting the synchronized code. F is wrong because notifyAll() notifies all the threads waiting on a particular locked object, not all threads waiting on any object.
Answer 8
E is correct. Synchronizing the public methods is sufficient to make this safe, so F is false. This class is not thread-safe unless some sort of synchronization protects the changing data.
B is not correct because although a StringBuffer is synchonized internally, we call append() multiple times, and nothing would prevent two simultaneous log() calls from mixing up their messages. C and D are not correct because if one method remains unsynchronized, it can run while the other is executing, which could result in reading the contents while one of the messages is incomplete, or worse.
Answer 9
G is correct. The code does not acquire a lock on t before calling t.wait(), so it throws an IllegalMonitorStateException. The method is synchronized, but it’s not synchronized on t so the exception will be thrown. If the wait were placed inside a synchronized(t) block, then the answer would have been D.
Answer 10
B is correct. The first line of main we’re constructing an instance of an anonymous inner class extending from SimpleThreadExample. So the SimpleThreadExample constructor runs and prints SimpleThreadExample. Next, main() invokes start() on the new thread instance, which causes the overridden run() method (the run() method in the anonymous inner class) to be invoked.
Answer 11
A, F, and H. A is a right answer because when synchronized instance methods are called on the same instance, they block each other. F and H can’t happen because synchronized static methods in the same class block each other, regardless of which instance was used to call the methods. (An instance is not required to call static methods; only the class.)
C could happen because synchronized instance methods called on different instances do not block each other. B, D, E, and G could all happen because instance methods and static methods lock on different objects, and do not block each other.
Answer 12
A, C, D, E, and F are correct. This may look like cena and orton are battling to cause the other to sleep() or wait()—but that’s not the case. Since sleep() is a static method, it affects the current thread, which is cena (even though the method is invoked using a reference to orton). That’s misleading but perfectly legal, and the Thread cena is able to sleep with no exception, printing A and C (after at least a 1-second delay). Meanwhile orton tries to call cena.wait()—but orton has not synchronized on cena, so calling cena.wait() immediately causes an IllegalMonitorStateException, and so orton prints D, E, and F. Although the order of the output is somewhat indeterminate (we have no way of knowing whether A is printed before D, for example) it is guaranteed that A, C, D, E, and F will all be printed in some order, eventually—so G is incorrect.
Answer 13
C and D are correct. Fragment I doesn’t start a new thread. Fragment II doesn’t compile. Fragment III creates a new thread but doesn’t start it. Fragment IV creates a new thread and invokes run() directly, but it doesn’t start the new thread. Fragment V creates and starts a new thread.
Answer 14
A is correct. The join() must be placed in a try/catch block. If it were, answers B and D would be correct. The join() causes the main thread to pause and join the end of the other thread, meaning "a2" must come last.
Answer 15
F is correct. With fragment I, the chat method is synchronized, so the two threads can’t swap back and forth. With either fragment, the first output must be yo.
Previous Chapter: Quick Review - Threads
Next Chapter: Other Topics of Importance
Questions:
Question 1
The following block of code creates a Thread using a Runnable target:
Runnable r = new MyRunnable();
Thread SimpleThreadExample = new Thread(r);
Which of the following classes can be used to create the target, so that the preceding code compiles correctly?
A. public class MyRunnable extends Runnable{public void run(){}}
B. public class MyRunnable extends Object{public void run(){}}
C. public class MyRunnable implements Runnable{public void run(){}}
D. public class MyRunnable implements Runnable{void run(){}}
E. public class MyRunnable implements Runnable{public void start(){}}
Question 2
Given:
3. class SimpleThreadExample extends Thread {
4. public static void main(String [] args) {
5. SimpleThreadExample t = new SimpleThreadExample();
6. Thread x = new Thread(t);
7. x.start();
8. }
9. public void run() {
10. for(int i=0;i<3;++i) {
11. System.out.print(i + "..");
12. }
13. }
14. }
What is the result of this code?
A. Compilation fails
B. 1..2..3..
C. 0..1..2..3..
D. 0..1..2..
E. An exception occurs at runtime
Question 3
Given:
3. class Test {
4. public static void main(String [] args) {
5. printStuff(args);
6. }
7. public static void printStuff(String[] lines) {
8. for(int i=0;i < lines.length;i++){
9. System.out.println(lines[i]);
10. Thread.currentThread().sleep(1000);
11. }
12. }
13. }
The static method Thread.currentThread() returns a reference to the currently executing Thread object. What is the result of this code?
A. Each String in the array lines will output, with a 1-second pause between lines
B. Each String in the array lines will output, with no pause in between because this method is not executed in a Thread
C. Each String in the array lines will output, and there is no guarantee there will be a pause because currentThread() may not retrieve this thread
D. This code will not compile
E. Each String in the lines array will print, with at least a one-second pause between lines
Question 4
Assume you have a class that holds two private variables: x and y. Which of the following pairs can prevent concurrent access problems in that class? (Choose all that apply.)
A. public int read(){return x+y;}
B. public void set(int x, int y){this.x=x;this.y=y;}
C. public synchronized int read(){return x+y;}
D. public synchronized void set(int x, int y){this.x=x;this.y=y;}
E. public int read(){synchronized(x){return x+y;}}
F. public void set(int x, int y){synchronized(x){this.x=x;this.y=y;}}
G. public int read(){synchronized(x){return x+y;}}
H. public void set(int x, int y){synchronized(y){this.x=x;this.y=y;}}
I. public synchronized(this) int read(){return x+y;}
J. public synchronized(this) void set(int x, int y){this.x=x;this.y=y;}
K. public int read(){synchronized(this){return x+y;}}
L. public void set(int x, int y){synchronized(this){this.x=x;this.y=y;}}
Question 5
Given:
1. public class TestWaitMethod {
2. public static void main(String [] args) {
3. System.out.print("1 ");
4. synchronized(args){
5. System.out.print("2 ");
6. try {
7. args.wait();
8. }
9. catch(InterruptedException e){}
10. }
11. System.out.print("3 ");
12. }
13. }
What is the result of trying to compile and run this program?
A. It fails to compile because the IllegalMonitorStateException of wait() is not dealt with in line 7
B. 1 2 3
C. 1 3
D. 1 2
E. At runtime, it throws an IllegalMonitorStateException when trying to wait
F. It will fail to compile because it has to be synchronized on the this object
Question 6
Assume the following method is properly synchronized and called from a thread A on an object B:
wait(2000);
After calling this method, when will the thread A become a candidate to get another turn at the CPU?
A. After object B is notified, or after two seconds
B. After the lock on B is released, or after two seconds
C. Two seconds after object B is notified
D. Two seconds after lock B is released
Question 7
Which are true? (Choose all that apply.)
A. The notifyAll() method must be called from a synchronized context
B. To call wait(), an object must own the lock on the thread
C. The notify() method is defined in class java.lang.Thread
D. When a thread is waiting as a result of wait(), it releases its lock
E. The notify() method causes a thread to immediately release its lock
F. The difference between notify() and notifyAll() is that notifyAll() notifies all waiting threads, regardless of the object they’re waiting on
Question 8
Given the scenario: This class is intended to allow users to write a series of messages, so that each message is identified with a timestamp and the name of the thread that wrote the message:
public class MyErrorLoggingUtilClass {
private StringBuilder contents = new StringBuilder();
public void log(String message) {
contents.append(System.currentTimeMillis());
contents.append(": ");
contents.append(Thread.currentThread().getName());
contents.append(message);
contents.append("\n");
}
public String getLogMessages() { return contents.toString(); }
}
How can we ensure that instances of this class can be safely used by multiple threads?
A. This class is already thread-safe
B. Replacing StringBuilder with StringBuffer will make this class thread-safe
C. Synchronize the log() method only
D. Synchronize the getLogMessages() method only
E. Synchronize both log() and getLogMessages()
F. This class cannot be made thread-safe
Question 9
Given:
public static synchronized void main(String[] args) throws
InterruptedException {
Thread t = new Thread();
t.start();
System.out.print("X");
t.wait(10000);
System.out.print("Y");
}
What is the result of this code?
A. It prints X and exits
B. It prints X and never exits
C. It prints XY and exits almost immeditately
D. It prints XY with a 10-second delay between X and Y
E. It prints XY with a 10000-second delay between X and Y
F. The code does not compile
G. An exception is thrown at runtime
Question 10
Given:
class SimpleThreadExample extends Thread {
SimpleThreadExample() {
System.out.print(" SimpleThreadExample");
}
public void run() {
System.out.print(" aaa");
}
public void run(String s) {
System.out.print(" bbb");
}
}
public class TestThreads {
public static void main (String [] args) {
Thread t = new SimpleThreadExample() {
public void run() {
System.out.print(" ccc");
}
};
t.start();
} }
What is the result?
A. ccc
B. SimpleThreadExample ccc
C. SimpleThreadExample aaa
D. ccc aaa
E. ccc aaa bbb
F. aaa ccc
G. Compilation fails
H. An exception is thrown at runtime
Question 11
Given:
public class ExampleThread {
synchronized void a() { doSomething(); }
static synchronized void b() { doSomething(); }
static void doSomething() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
}
public static void main(String[] args) {
final ExampleThread x = new ExampleThread();
final ExampleThread y = new ExampleThread();
Runnable runnable = new Runnable() {
public void run() {
int option = (int) (Math.random() * 4);
switch (option) {
case 0: x.a(); break;
case 1: x.b(); break;
case 2: y.a(); break;
case 3: y.b(); break;
}
}
};
Thread thread1 = new Thread(runnable);
Thread thread2 = new Thread(runnable);
thread1.start();
thread2.start();
}
}
Which of the following pairs of method invocations could NEVER be executing at the same time? (Choose all that apply.)
A. x.a() in thread1, and x.a() in thread2
B. x.a() in thread1, and x.b() in thread2
C. x.a() in thread1, and y.a() in thread2
D. x.a() in thread1, and y.b() in thread2
E. x.b() in thread1, and x.a() in thread2
F. x.b() in thread1, and x.b() in thread2
G. x.b() in thread1, and y.a() in thread2
H. x.b() in thread1, and y.b() in thread2
Question 12
Given:
public class MultipleThreadExample {
static Thread cena, orton;
public static void main(String[] args) {
cena = new Thread() {
public void run() {
System.out.println("A");
try {
orton.sleep(1000);
} catch (Exception e) {
System.out.println("B");
}
System.out.println("C");
}
};
orton = new Thread() {
public void run() {
System.out.println("D");
try {
cena.wait();
} catch (Exception e) {
System.out.println("E");
}
System.out.println("F");
}
};
cena.start();
orton.start();
}
}
Which letters will eventually appear somewhere in the output? (Choose all that apply.)
A. A
B. B
C. C
D. D
E. E
F. F
G. The answer cannot be reliably determined
H. The code does not compile
Question 13
Given:
3. public class Runner implements Runnable {
4. void go(long id) {
5. System.out.println(id);
6. }
7. public static void main(String[] args) {
8. System.out.print(Thread.currentThread().getId() + " ");
9. // insert code here
10. }
11. public void run() { go(Thread.currentThread().getId()); }
12. }
And given the following five fragments:
I. new Runner().run();
II. new Runner().start();
III. new Thread(new Runner());
IV. new Thread(new Runner()).run();
V. new Thread(new Runner()).start();
When the five fragments are inserted, one at a time at line 9, which are true? (Choose all that apply.)
A. All five will compile
B. Only one might produce the output 4 4
C. Only one might produce the output 4 2
D. Exactly two might produce the output 4 4
E. Exactly two might produce the output 4 2
F. Exactly three might produce the output 4 4
G. Exactly three might produce the output 4 2
Question 14
Given:
3. public class Awesome implements Runnable {
4. public static void main(String[] args) {
5. Thread t = new Thread(new Awesome());
6. t.start();
7. System.out.print("a1 ");
8. t.join();
9. System.out.print("a2 ");
10. }
11. public void run() {
12. System.out.print("b1 ");
13. System.out.print("b2 ");
14. }
15. }
Which are true? (Choose all that apply.)
A. Compilation fails
B. The output could be b1 b2 a1 a2
C. The output could be a1 a2 b1 b2
D. The output could be a1 b1 b2 a2
E. The output could be a1 b1 a2 b2
F. An exception is thrown at runtime
Question 15
Given:
3. class Friends {
4. static long flag = 0;
5. // insert code here
6. if(flag == 0) flag = id;
7. for(int x = 1; x < 3; x++) {
8. if(flag == id) System.out.print("yo ");
9. else System.out.print("Friend ");
10. }
11. }
12. }
13. public class FriendsHangOut implements Runnable {
14. static Friends d;
15. public static void main(String[] args) {
16. new FriendsHangOut().go();
17. }
18. void go() {
19. d = new Friends();
20. new Thread(new FriendsHangOut()).start();
21. new Thread(new FriendsHangOut()).start();
22. }
23. public void run() {
24. d.chat(Thread.currentThread().getId());
25. }
26. }
And given these two fragments:
I. synchronized void chat(long id) {
II. void chat(long id) {
When fragment I or fragment II is inserted at line 5, which are true? (Choose all that apply.)
A. An exception is thrown at runtime
B. With fragment I, compilation fails
C. With fragment II, compilation fails
D. With fragment I, the output could be yo Friend Friend yo
E. With fragment I, the output could be Friend Friend yo yo
F. With fragment II, the output could be yo Friend Friend yo
Answers:
Answer 1
C is correct. The class implements the Runnable interface with a legal run() method.
A is incorrect because interfaces are implemented, not extended. B is incorrect because even though the class has a valid public void run() method, it does not implement the Runnable interface. D is incorrect because the run() method must be public. E is incorrect because the method to implement is run(), not start().
Answer 2
D is correct. The thread SimpleThreadExample will start and loop three times (from 0 to 2).
A is incorrect because the Thread class implements the Runnable interface; therefore, in line 5, Thread can take an object of type Thread as an argument in the constructor (this is NOT recommended). B and C are incorrect because the variable i in the for loop starts with a value of 0 and ends with a value of 2.
Answer 3
D is correct. The sleep() method must be enclosed in a try/catch block, or the method printStuff() must declare it throws the InterruptedException.
E is incorrect, but it would be correct if the InterruptedException was dealt with (A is too precise). B is incorrect (even if the InterruptedException was dealt with) because all Java code, including the main() method, runs in threads. C is incorrect. The sleep() method is static, it always affects the currently executing thread.
Answer 4
B and F are correct. By marking the methods as synchronized, the threads will get the lock of the this object before proceeding. Only one thread will be setting or reading at any given moment, thereby assuring that read() always returns the addition of a valid pair.
A is incorrect because it is not synchronized; therefore, there is no guarantee that the values added by the read() method belong to the same pair. C and D are incorrect; only objects can be used to synchronize on. E fails—it is not possible to select other objects (even this) to synchronize on when declaring a method as synchronized.
Answer 5
D is correct. 1 and 2 will be printed, but there will be no return from the wait call because no other thread will notify the main thread, so 3 will never be printed. It’s frozen at line 7.
A is incorrect; IllegalMonitorStateException is an unchecked exception. B and C are incorrect; 3 will never be printed, since this program will wait forever. E is incorrect because IllegalMonitorStateException will never be thrown because the wait() is done on args within a block of code synchronized on args. F is incorrect because any object can be used to synchronize on and this and static don’t mix.
Answer 6
A is correct. Either of the two events will make the thread a candidate for running again.
B is incorrect because a waiting thread will not return to runnable when the lock is released, unless a notification occurs. C is incorrect because the thread will become a candidate immediately after notification. D is also incorrect because a thread will not come out of a waiting pool just because a lock has been released.
Answer 7
A is correct because notifyAll() (and wait() and notify()) must be called from within a synchronized context. D is a correct statement.
B is incorrect because to call wait(), the thread must own the lock on the object that wait() is being invoked on, not the other way around. C is wrong because notify() is defined in java.lang.Object. E is wrong because notify() will not cause a thread to release its locks. The thread can only release its locks by exiting the synchronized code. F is wrong because notifyAll() notifies all the threads waiting on a particular locked object, not all threads waiting on any object.
Answer 8
E is correct. Synchronizing the public methods is sufficient to make this safe, so F is false. This class is not thread-safe unless some sort of synchronization protects the changing data.
B is not correct because although a StringBuffer is synchonized internally, we call append() multiple times, and nothing would prevent two simultaneous log() calls from mixing up their messages. C and D are not correct because if one method remains unsynchronized, it can run while the other is executing, which could result in reading the contents while one of the messages is incomplete, or worse.
Answer 9
G is correct. The code does not acquire a lock on t before calling t.wait(), so it throws an IllegalMonitorStateException. The method is synchronized, but it’s not synchronized on t so the exception will be thrown. If the wait were placed inside a synchronized(t) block, then the answer would have been D.
Answer 10
B is correct. The first line of main we’re constructing an instance of an anonymous inner class extending from SimpleThreadExample. So the SimpleThreadExample constructor runs and prints SimpleThreadExample. Next, main() invokes start() on the new thread instance, which causes the overridden run() method (the run() method in the anonymous inner class) to be invoked.
Answer 11
A, F, and H. A is a right answer because when synchronized instance methods are called on the same instance, they block each other. F and H can’t happen because synchronized static methods in the same class block each other, regardless of which instance was used to call the methods. (An instance is not required to call static methods; only the class.)
C could happen because synchronized instance methods called on different instances do not block each other. B, D, E, and G could all happen because instance methods and static methods lock on different objects, and do not block each other.
Answer 12
A, C, D, E, and F are correct. This may look like cena and orton are battling to cause the other to sleep() or wait()—but that’s not the case. Since sleep() is a static method, it affects the current thread, which is cena (even though the method is invoked using a reference to orton). That’s misleading but perfectly legal, and the Thread cena is able to sleep with no exception, printing A and C (after at least a 1-second delay). Meanwhile orton tries to call cena.wait()—but orton has not synchronized on cena, so calling cena.wait() immediately causes an IllegalMonitorStateException, and so orton prints D, E, and F. Although the order of the output is somewhat indeterminate (we have no way of knowing whether A is printed before D, for example) it is guaranteed that A, C, D, E, and F will all be printed in some order, eventually—so G is incorrect.
Answer 13
C and D are correct. Fragment I doesn’t start a new thread. Fragment II doesn’t compile. Fragment III creates a new thread but doesn’t start it. Fragment IV creates a new thread and invokes run() directly, but it doesn’t start the new thread. Fragment V creates and starts a new thread.
Answer 14
A is correct. The join() must be placed in a try/catch block. If it were, answers B and D would be correct. The join() causes the main thread to pause and join the end of the other thread, meaning "a2" must come last.
Answer 15
F is correct. With fragment I, the chat method is synchronized, so the two threads can’t swap back and forth. With either fragment, the first output must be yo.
Previous Chapter: Quick Review - Threads
Next Chapter: Other Topics of Importance
Quick Review: Chapters 55 to 61 (Threads)
This is going to be the last quick recap chapter in this SCJP Series. This will cover the important points about Threads.
Defining, Instantiating, and Starting Threads
* Threads can be created by extending Thread and overriding the public void run() method.
* Thread objects can also be created by calling the Thread constructor that takes a Runnable argument. The Runnable object is said to be the target of the thread.
* You can call start() on a Thread object only once. If start() is called more than once on a Thread object, it will throw a RuntimeException.
* It is legal to create many Thread objects using the same Runnable object as the target.
* When a Thread object is created, it does not become a thread of execution until its start() method is invoked. When a Thread object exists but hasn’t been started, it is in the new state and is not considered alive.
Transitioning Between Thread States
* Once a new thread is started, it will always enter the runnable state.
* The thread scheduler can move a thread back and forth between the runnable state and the running state.
* For a typical single-processor machine, only one thread can be running at a time, although many threads may be in the runnable state.
* There is no guarantee that the order in which threads were started determines the order in which they’ll run.
* There’s no guarantee that threads will take turns in any fair way. It’s up to the thread scheduler, as determined by the particular virtual machine implementation. If you want a guarantee that your threads will take turns regardless of the underlying JVM, you can use the sleep() method. This prevents one thread from hogging the running process while another thread starves.
* A running thread may enter a blocked/waiting state by a wait(), sleep(), or join() call.
* A running thread may enter a blocked/waiting state because it can’t acquire the lock for a synchronized block of code.
* When the sleep or wait is over, or an object’s lock becomes available, the thread can only reenter the runnable state. It will go directly from waiting to running (well, for all practical purposes anyway).
* A dead thread cannot be started again.
Sleep, Yield, and Join
* Sleeping is used to delay execution for a period of time, and no locks are released when a thread goes to sleep.
* A sleeping thread is guaranteed to sleep for at least the time specified in the argument to the sleep() method (unless it’s interrupted), but there is no guarantee as to when the newly awakened thread will actually return to running.
* The sleep() method is a static method that sleeps the currently executing thread’s state. One thread cannot tell another thread to sleep.
* The setPriority() method is used on Thread objects to give threads a priority of between 1 (low) and 10 (high), although priorities are not guaranteed, and not all JVMs recognize 10 distinct priority levels—some levels may be treated as effectively equal.
* If not explicitly set, a thread’s priority will have the same priority as the priority of the thread that created it.
* The yield() method may cause a running thread to back out if there are runnable threads of the same priority. There is no guarantee that this will happen, and there is no guarantee that when the thread backs out there will be a different thread selected to run. A thread might yield and then immediately reenter the running state.
* The closest thing to a guarantee is that at any given time, when a thread is running it will usually not have a lower priority than any thread in the runnable state. If a low-priority thread is running when a high-priority thread enters runnable, the JVM will usually preempt the running low-priority thread and put the high-priority thread in.
* When one thread calls the join() method of another thread, the currently running thread will wait until the thread it joins with has completed. Think of the join() method as saying, “Hey thread, I want to join on to your end. Let me know when you’re done, so I can enter the runnable state.”
Synchronization
* synchronized methods prevent more than one thread from accessing an object’s critical method code simultaneously.
* You can use the synchronized keyword as a method modifier, or to start a synchronized block of code.
* To synchronize a block of code, you must specify an argument that is the object whose lock you want to synchronize on.
* While only one thread can be accessing synchronized code of a particular instance, multiple threads can still access the same object’s unsynchronized code.
* When a thread goes to sleep, its locks will be unavailable to other threads.
* static methods can be synchronized, using the lock from the java.lang.Class instance representing that class.
Thread Communication
* The wait() method lets a thread say, “I got nothing to do, so put me in your waiting pool and notify me when something happens that I care about.”
* The notify() method is used to send a signal to one and only one of the threads that are waiting in that same object’s waiting pool.
* The notify() method can NOT specify which waiting thread to notify.
* The method notifyAll() works in the same way as notify(), only it sends the signal to all of the threads waiting on the object.
* All three methods—wait(), notify(), and notifyAll()—must be called from within a synchronized context! A thread invokes wait() or notify() on a particular object, and the thread must currently hold the lock on that object.
Deadlocks
* Deadlocking is when thread execution grinds to a halt because the code is waiting for locks to be removed from objects.
* Deadlocking can occur when a locked object attempts to access another locked object that is trying to access the first locked object. In other words, both threads are waiting for each other’s locks to be released; therefore, the locks will never be released!
Previous Chapter: Chapter 61 - Thread Interaction
Next Chapter: Self Test - Chapters 55 to 61
Defining, Instantiating, and Starting Threads
* Threads can be created by extending Thread and overriding the public void run() method.
* Thread objects can also be created by calling the Thread constructor that takes a Runnable argument. The Runnable object is said to be the target of the thread.
* You can call start() on a Thread object only once. If start() is called more than once on a Thread object, it will throw a RuntimeException.
* It is legal to create many Thread objects using the same Runnable object as the target.
* When a Thread object is created, it does not become a thread of execution until its start() method is invoked. When a Thread object exists but hasn’t been started, it is in the new state and is not considered alive.
Transitioning Between Thread States
* Once a new thread is started, it will always enter the runnable state.
* The thread scheduler can move a thread back and forth between the runnable state and the running state.
* For a typical single-processor machine, only one thread can be running at a time, although many threads may be in the runnable state.
* There is no guarantee that the order in which threads were started determines the order in which they’ll run.
* There’s no guarantee that threads will take turns in any fair way. It’s up to the thread scheduler, as determined by the particular virtual machine implementation. If you want a guarantee that your threads will take turns regardless of the underlying JVM, you can use the sleep() method. This prevents one thread from hogging the running process while another thread starves.
* A running thread may enter a blocked/waiting state by a wait(), sleep(), or join() call.
* A running thread may enter a blocked/waiting state because it can’t acquire the lock for a synchronized block of code.
* When the sleep or wait is over, or an object’s lock becomes available, the thread can only reenter the runnable state. It will go directly from waiting to running (well, for all practical purposes anyway).
* A dead thread cannot be started again.
Sleep, Yield, and Join
* Sleeping is used to delay execution for a period of time, and no locks are released when a thread goes to sleep.
* A sleeping thread is guaranteed to sleep for at least the time specified in the argument to the sleep() method (unless it’s interrupted), but there is no guarantee as to when the newly awakened thread will actually return to running.
* The sleep() method is a static method that sleeps the currently executing thread’s state. One thread cannot tell another thread to sleep.
* The setPriority() method is used on Thread objects to give threads a priority of between 1 (low) and 10 (high), although priorities are not guaranteed, and not all JVMs recognize 10 distinct priority levels—some levels may be treated as effectively equal.
* If not explicitly set, a thread’s priority will have the same priority as the priority of the thread that created it.
* The yield() method may cause a running thread to back out if there are runnable threads of the same priority. There is no guarantee that this will happen, and there is no guarantee that when the thread backs out there will be a different thread selected to run. A thread might yield and then immediately reenter the running state.
* The closest thing to a guarantee is that at any given time, when a thread is running it will usually not have a lower priority than any thread in the runnable state. If a low-priority thread is running when a high-priority thread enters runnable, the JVM will usually preempt the running low-priority thread and put the high-priority thread in.
* When one thread calls the join() method of another thread, the currently running thread will wait until the thread it joins with has completed. Think of the join() method as saying, “Hey thread, I want to join on to your end. Let me know when you’re done, so I can enter the runnable state.”
Synchronization
* synchronized methods prevent more than one thread from accessing an object’s critical method code simultaneously.
* You can use the synchronized keyword as a method modifier, or to start a synchronized block of code.
* To synchronize a block of code, you must specify an argument that is the object whose lock you want to synchronize on.
* While only one thread can be accessing synchronized code of a particular instance, multiple threads can still access the same object’s unsynchronized code.
* When a thread goes to sleep, its locks will be unavailable to other threads.
* static methods can be synchronized, using the lock from the java.lang.Class instance representing that class.
Thread Communication
* The wait() method lets a thread say, “I got nothing to do, so put me in your waiting pool and notify me when something happens that I care about.”
* The notify() method is used to send a signal to one and only one of the threads that are waiting in that same object’s waiting pool.
* The notify() method can NOT specify which waiting thread to notify.
* The method notifyAll() works in the same way as notify(), only it sends the signal to all of the threads waiting on the object.
* All three methods—wait(), notify(), and notifyAll()—must be called from within a synchronized context! A thread invokes wait() or notify() on a particular object, and the thread must currently hold the lock on that object.
Deadlocks
* Deadlocking is when thread execution grinds to a halt because the code is waiting for locks to be removed from objects.
* Deadlocking can occur when a locked object attempts to access another locked object that is trying to access the first locked object. In other words, both threads are waiting for each other’s locks to be released; therefore, the locks will never be released!
Previous Chapter: Chapter 61 - Thread Interaction
Next Chapter: Self Test - Chapters 55 to 61
Labels:
deadlock,
deadlocks,
java threads,
making threads sleep,
quick recap,
quick review,
runnable,
running,
synchronization,
thread deadlocks,
threads,
thread synchronization,
waiting
| Reactions: |
Friday, February 25, 2011
Quick Review: Chapters 52 to 55 (Inner classes)
Below is a quick recap/review of the previous chapters that we had about inner classes. So, lets get started!!!
Inner Classes
* A “regular” inner class is declared inside the curly braces of another class, but outside any method or other code block.
* An inner class is a full-fledged member of the enclosing (outer) class, so it can be marked with an access modifier as well as the abstract or final modifiers. (Never both abstract and final together—remember that abstract must be subclassed, whereas final cannot be subclassed).
* An inner class instance shares a special relationship with an instance of the enclosing class. This relationship gives the inner class access to all of the outer class’s members, including those marked private.
* To instantiate an inner class, you must have a reference to an instance of the outer class.
* From code within the enclosing class, you can instantiate the inner class using only the name of the inner class, as follows:
MyInner mi = new MyInner();
* From code outside the enclosing class’s instance methods, you can instantiate the inner class only by using both the inner and outer class names, and a reference to the outer class as follows:
MyOuter mo = new MyOuter();
MyOuter.MyInner inner = mo.new MyInner();
* From code within the inner class, the keyword this holds a reference to the inner class instance. To reference the outer this (in other words, the instance of the outer class that this inner instance is tied to) precede the keyword this with the outer class name as follows: MyOuter.this;
Method-Local Inner Classes
* A method-local inner class is defined within a method of the enclosing class.
* For the inner class to be used, you must instantiate it, and that instantiation must happen within the same method, but after the class definition code.
* A method-local inner class cannot use variables declared within the method (including parameters) unless those variables are marked final.
* The only modifiers you can apply to a method-local inner class are abstract and final. (Never both at the same time, though.)
Anonymous Inner Classes
* Anonymous inner classes have no name, and their type must be either a subclass of the named type or an implementer of the named interface.
* An anonymous inner class is always created as part of a statement; don’t forget to close the statement after the class definition with a curly brace. This is a rare case in Java, a curly brace followed by a semicolon.
* Because of polymorphism, the only methods you can call on an anonymous inner class reference are those defined in the reference variable class (or interface), even though the anonymous class is really a subclass or implementer of the reference variable type.
* An anonymous inner class can extend one subclass or implement one interface. Unlike non-anonymous classes (inner or otherwise), an anonymous inner class cannot do both. In other words, it cannot both extend a class and implement an interface, nor can it implement more than one interface.
* An argument-defined inner class is declared, defined, and automatically instantiated as part of a method invocation. The key to remember is that the class is being defined within a method argument, so the syntax will end the class definition with a curly brace, followed by a closing parenthesis to end the method call, followed by a semicolon to end the statement: });
Static Inner Classes
* Static Inner classes are inner classes marked with the static modifier.
* A static nested class is not an inner class, it’s a top-level nested class.
* Because the nested class is static, it does not share any special relationship with an instance of the outer class. In fact, you don’t need an instance of the outer class to instantiate a static nested class.
* Instantiating a static nested class requires using both the outer and nested class names as follows:
BigOuter.Nested n = new BigOuter.Nested();
* A static nested class cannot access non-static members of the outer class, since it does not have an implicit reference to any outer instance (in other words, the nested class instance does not get an outer this reference).
Previous Chapter: Chapter 55 - Static Inner Classes
Next Chapter: Self Test - Chapters 52 to 55
Inner Classes
* A “regular” inner class is declared inside the curly braces of another class, but outside any method or other code block.
* An inner class is a full-fledged member of the enclosing (outer) class, so it can be marked with an access modifier as well as the abstract or final modifiers. (Never both abstract and final together—remember that abstract must be subclassed, whereas final cannot be subclassed).
* An inner class instance shares a special relationship with an instance of the enclosing class. This relationship gives the inner class access to all of the outer class’s members, including those marked private.
* To instantiate an inner class, you must have a reference to an instance of the outer class.
* From code within the enclosing class, you can instantiate the inner class using only the name of the inner class, as follows:
MyInner mi = new MyInner();
* From code outside the enclosing class’s instance methods, you can instantiate the inner class only by using both the inner and outer class names, and a reference to the outer class as follows:
MyOuter mo = new MyOuter();
MyOuter.MyInner inner = mo.new MyInner();
* From code within the inner class, the keyword this holds a reference to the inner class instance. To reference the outer this (in other words, the instance of the outer class that this inner instance is tied to) precede the keyword this with the outer class name as follows: MyOuter.this;
Method-Local Inner Classes
* A method-local inner class is defined within a method of the enclosing class.
* For the inner class to be used, you must instantiate it, and that instantiation must happen within the same method, but after the class definition code.
* A method-local inner class cannot use variables declared within the method (including parameters) unless those variables are marked final.
* The only modifiers you can apply to a method-local inner class are abstract and final. (Never both at the same time, though.)
Anonymous Inner Classes
* Anonymous inner classes have no name, and their type must be either a subclass of the named type or an implementer of the named interface.
* An anonymous inner class is always created as part of a statement; don’t forget to close the statement after the class definition with a curly brace. This is a rare case in Java, a curly brace followed by a semicolon.
* Because of polymorphism, the only methods you can call on an anonymous inner class reference are those defined in the reference variable class (or interface), even though the anonymous class is really a subclass or implementer of the reference variable type.
* An anonymous inner class can extend one subclass or implement one interface. Unlike non-anonymous classes (inner or otherwise), an anonymous inner class cannot do both. In other words, it cannot both extend a class and implement an interface, nor can it implement more than one interface.
* An argument-defined inner class is declared, defined, and automatically instantiated as part of a method invocation. The key to remember is that the class is being defined within a method argument, so the syntax will end the class definition with a curly brace, followed by a closing parenthesis to end the method call, followed by a semicolon to end the statement: });
Static Inner Classes
* Static Inner classes are inner classes marked with the static modifier.
* A static nested class is not an inner class, it’s a top-level nested class.
* Because the nested class is static, it does not share any special relationship with an instance of the outer class. In fact, you don’t need an instance of the outer class to instantiate a static nested class.
* Instantiating a static nested class requires using both the outer and nested class names as follows:
BigOuter.Nested n = new BigOuter.Nested();
* A static nested class cannot access non-static members of the outer class, since it does not have an implicit reference to any outer instance (in other words, the nested class instance does not get an outer this reference).
Previous Chapter: Chapter 55 - Static Inner Classes
Next Chapter: Self Test - Chapters 52 to 55
Labels:
anonymous inner class,
inner class,
inner classes,
method local inner class,
quick recap,
quick review,
static inner class
| Reactions: |
Quick Review: Chapters 38 to 51
This chapter is going to be the Quick recap/review of the concepts we learnt in the previous chapters on collections.
So, lets get started!!!
Overriding hashCode() and equals()
* equals(), hashCode(), and toString() are public.
* Override toString() so that System.out.println() or other methods can see something useful, like your object’s state.
* Use == to determine if two reference variables refer to the same object.
* Use equals() to determine if two objects are meaningfully equivalent.
* If you don’t override equals(), your objects won’t be useful hashing keys.
* If you don’t override equals(), different objects can’t be considered equal.
* Strings and wrappers override equals() and make good hashing keys.
* When overriding equals(), use the instanceof operator to be sure you’re evaluating an appropriate class.
* When overriding equals(), compare the objects’ significant attributes.
* Highlights of the equals() contract:
* Reflexive: x.equals(x) is true.
* Symmetric: If x.equals(y) is true, then y.equals(x) must be true.
* Transitive: If x.equals(y) is true, and y.equals(z) is true, then z.equals(x) is true.
* Consistent: Multiple calls to x.equals(y) will return the same result.
* Null: If x is not null, then x.equals(null) is false.
* If x.equals(y) is true, then x.hashCode() == y.hashCode() is true.
* If you override equals(), override hashCode().
* HashMap, HashSet, Hashtable, LinkedHashMap, & LinkedHashSet use hashing.
* An appropriate hashCode() override sticks to the hashCode() contract.
* An efficient hashCode() override distributes keys evenly across its buckets.
* An overridden equals() must be at least as precise as its hashCode() mate.
* To reiterate: if two objects are equal, their hashcodes must be equal.
* It’s legal for a hashCode() method to return the same value for all instances (although in practice it’s very inefficient).
* Highlights of the hashCode() contract:
* Consistent: multiple calls to x.hashCode() return the same integer.
* If x.equals(y) is true, x.hashCode() == y.hashCode() is true.
* If x.equals(y) is false, then x.hashCode() == y.hashCode() can be either true or false, but false will tend to create better efficiency.
* transient variables aren’t appropriate for equals() and hashCode().
Collections
* Common collection activities include adding objects, removing objects, verifying object inclusion, retrieving objects, and iterating.
* Three meanings for “collection”:
* collection Represents the data structure in which objects are stored
* Collection java.util interface from which Set and List extend
* Collections A class that holds static collection utility methods
Four basic flavors of collections include Lists, Sets, Maps, Queues:
* Lists of things Ordered, duplicates allowed, with an index.
* Sets of things May or may not be ordered and/or sorted; duplicates not allowed.
* Maps of things with keys May or may not be ordered and/or sorted; duplicate keys are not allowed.
* Queues of things to process Ordered by FIFO or by priority.
* Four basic sub-flavors of collections Sorted, Unsorted, Ordered, Unordered.
* Ordered Iterating through a collection in a specific, non-random order.
* Sorted Iterating through a collection in a sorted order.
* Sorting can be alphabetic, numeric, or programmer-defined.
Key Attributes of Common Collection Classes
* ArrayList: Fast iteration and fast random access.
* Vector: It’s like a slower ArrayList, but it has synchronized methods.
* LinkedList: Good for adding elements to the ends, i.e., stacks and queues.
* HashSet: Fast access, assures no duplicates, provides no ordering.
* LinkedHashSet: No duplicates; iterates by insertion order.
* TreeSet: No duplicates; iterates in sorted order.
* HashMap: Fastest updates (key/values); allows one null key, many null values.
* Hashtable: Like a slower HashMap (as with Vector, due to its synchronized methods). No null values or null keys allowed.
* LinkedHashMap: Faster iterations; iterates by insertion order or last accessed; allows one null key, many null values.
* TreeMap: A sorted map.
* PriorityQueue: A to-do list ordered by the elements’ priority.
Using Collection Classes
* Collections hold only Objects, but primitives can be autoboxed.
* Iterate with the enhanced for, or with an Iterator via hasNext() & next().
* hasNext() determines if more elements exist; the Iterator does NOT move.
* next() returns the next element AND moves the Iterator forward.
* To work correctly, a Map’s keys must override equals() and hashCode().
* Queues use offer() to add an element, poll() to remove the head of the queue, and peek() to look at the head of a queue.
* As of Java 6 TreeSets and TreeMaps have new navigation methods like floor() and higher().
* You can create/extend “backed” sub-copies of TreeSets and TreeMaps.
Sorting and Searching Arrays and Lists
* Sorting can be in natural order, or via a Comparable or many Comparators.
* Implement Comparable using compareTo(); provides only one sort order.
* Create many Comparators to sort a class many ways; implement compare().
* To be sorted and searched, a List’s elements must be comparable.
* To be searched, an array or List must first be sorted.
Utility Classes: Collections and Arrays
* Both of these java.util classes provide
* A sort() method. Sort using a Comparator or sort using natural order.
* A binarySearch() method. Search a pre-sorted array or List.
* Arrays.asList() creates a List from an array and links them together.
* Collections.reverse() reverses the order of elements in a List.
* Collections.reverseOrder() returns a Comparator that sorts in reverse.
* Lists and Sets have a toArray() method to create arrays.
Generics
* Generics let you enforce compile-time type safety on Collections (or other classes and methods declared using generic type parameters).
* An ArrayList< Car > can accept references of type Ferrari, Bmw, or any other subtype of Car
* When using generic collections, a cast is not needed to get (declared type) elements out of the collection. With non-generic collections, a cast is required:
List< String > gList = new ArrayList< String >();
List list = new ArrayList();
// more code
String s = gList.get(0); // no cast needed
String s = (String)list.get(0); // cast required
* You can pass a generic collection into a method that takes a non-generic collection, but the results may be disastrous. The compiler can’t stop the method from inserting the wrong type into the previously type safe collection.
* If the compiler can recognize that non-type-safe code is potentially endangering something you originally declared as type-safe, you will get a compiler warning. For instance, if you pass a List< String > into a method declared as
void foo(List aList) { aList.add(anInteger); }
* You’ll get a warning because add() is potentially “unsafe”.
* “Compiles without error” is not the same as “compiles without warnings.” A compilation warning is not considered a compilation error or failure.
* Generic type information does not exist at runtime—it is for compile-time safety only. Mixing generics with legacy code can create compiled code that may throw an exception at runtime.
* Polymorphic assignments applies only to the base type, not the generic type parameter. You can say
List< Car > aList = new ArrayList< Car >(); // yes
You can’t say
List< Car > aList = new ArrayList< Ferrari >(); // no
* The polymorphic assignment rule applies everywhere an assignment can be made. The following are NOT allowed:
void foo(List< Car > aList) { } // cannot take a List
List< Car > bar() { } // cannot return a List
* Wildcard syntax allows a generic method, accept subtypes (or supertypes) of the declared type of the method argument:
void addD(List< Car > d) {} // can take only < Car >
void addD(List< ? extends Car >) {} // take a < Car > or < Ferrari >
* The wildcard keyword extends is used to mean either “extends” or “implements.” So in extends Car>, Car can be a class or an interface.
* When using a wildcard, List< ? extends Car >, the collection can be accessed but not modified.
* When using a wildcard, List< ? >, any generic type can be assigned to the reference, but for access only, no modifications.
* List< Object > refers only to a List< Object >, while List< ? > or List< ? extends Object > can hold any type of object, but for access only.
* Declaration conventions for generics use T for type and E for element:
public interface List< E > // API declaration for List
boolean add(E o) // List.add() declaration
* The generics type identifier can be used in class, method, and variable declarations:
class Foo { } // a class
T anInstance; // an instance variable
Foo(T aRef) {} // a constructor argument
void bar(T aRef) {} // a method argument
T baz() {} // a return type
The compiler will substitute the actual type.
* You can use more than one parameterized type in a declaration:
public class UseTwo { }
* You can declare a generic method using a type not defined in the class:
public void makeList(T t) { }
is NOT using T as the return type. This method has a void return type, but to use T within the method’s argument you must declare the, which happens before the return type.
Previous Chapter: Chapter 51 - Generics
Next Chapter: Self Test - Chapters 38 to 51
So, lets get started!!!
Overriding hashCode() and equals()
* equals(), hashCode(), and toString() are public.
* Override toString() so that System.out.println() or other methods can see something useful, like your object’s state.
* Use == to determine if two reference variables refer to the same object.
* Use equals() to determine if two objects are meaningfully equivalent.
* If you don’t override equals(), your objects won’t be useful hashing keys.
* If you don’t override equals(), different objects can’t be considered equal.
* Strings and wrappers override equals() and make good hashing keys.
* When overriding equals(), use the instanceof operator to be sure you’re evaluating an appropriate class.
* When overriding equals(), compare the objects’ significant attributes.
* Highlights of the equals() contract:
* Reflexive: x.equals(x) is true.
* Symmetric: If x.equals(y) is true, then y.equals(x) must be true.
* Transitive: If x.equals(y) is true, and y.equals(z) is true, then z.equals(x) is true.
* Consistent: Multiple calls to x.equals(y) will return the same result.
* Null: If x is not null, then x.equals(null) is false.
* If x.equals(y) is true, then x.hashCode() == y.hashCode() is true.
* If you override equals(), override hashCode().
* HashMap, HashSet, Hashtable, LinkedHashMap, & LinkedHashSet use hashing.
* An appropriate hashCode() override sticks to the hashCode() contract.
* An efficient hashCode() override distributes keys evenly across its buckets.
* An overridden equals() must be at least as precise as its hashCode() mate.
* To reiterate: if two objects are equal, their hashcodes must be equal.
* It’s legal for a hashCode() method to return the same value for all instances (although in practice it’s very inefficient).
* Highlights of the hashCode() contract:
* Consistent: multiple calls to x.hashCode() return the same integer.
* If x.equals(y) is true, x.hashCode() == y.hashCode() is true.
* If x.equals(y) is false, then x.hashCode() == y.hashCode() can be either true or false, but false will tend to create better efficiency.
* transient variables aren’t appropriate for equals() and hashCode().
Collections
* Common collection activities include adding objects, removing objects, verifying object inclusion, retrieving objects, and iterating.
* Three meanings for “collection”:
* collection Represents the data structure in which objects are stored
* Collection java.util interface from which Set and List extend
* Collections A class that holds static collection utility methods
Four basic flavors of collections include Lists, Sets, Maps, Queues:
* Lists of things Ordered, duplicates allowed, with an index.
* Sets of things May or may not be ordered and/or sorted; duplicates not allowed.
* Maps of things with keys May or may not be ordered and/or sorted; duplicate keys are not allowed.
* Queues of things to process Ordered by FIFO or by priority.
* Four basic sub-flavors of collections Sorted, Unsorted, Ordered, Unordered.
* Ordered Iterating through a collection in a specific, non-random order.
* Sorted Iterating through a collection in a sorted order.
* Sorting can be alphabetic, numeric, or programmer-defined.
Key Attributes of Common Collection Classes
* ArrayList: Fast iteration and fast random access.
* Vector: It’s like a slower ArrayList, but it has synchronized methods.
* LinkedList: Good for adding elements to the ends, i.e., stacks and queues.
* HashSet: Fast access, assures no duplicates, provides no ordering.
* LinkedHashSet: No duplicates; iterates by insertion order.
* TreeSet: No duplicates; iterates in sorted order.
* HashMap: Fastest updates (key/values); allows one null key, many null values.
* Hashtable: Like a slower HashMap (as with Vector, due to its synchronized methods). No null values or null keys allowed.
* LinkedHashMap: Faster iterations; iterates by insertion order or last accessed; allows one null key, many null values.
* TreeMap: A sorted map.
* PriorityQueue: A to-do list ordered by the elements’ priority.
Using Collection Classes
* Collections hold only Objects, but primitives can be autoboxed.
* Iterate with the enhanced for, or with an Iterator via hasNext() & next().
* hasNext() determines if more elements exist; the Iterator does NOT move.
* next() returns the next element AND moves the Iterator forward.
* To work correctly, a Map’s keys must override equals() and hashCode().
* Queues use offer() to add an element, poll() to remove the head of the queue, and peek() to look at the head of a queue.
* As of Java 6 TreeSets and TreeMaps have new navigation methods like floor() and higher().
* You can create/extend “backed” sub-copies of TreeSets and TreeMaps.
Sorting and Searching Arrays and Lists
* Sorting can be in natural order, or via a Comparable or many Comparators.
* Implement Comparable using compareTo(); provides only one sort order.
* Create many Comparators to sort a class many ways; implement compare().
* To be sorted and searched, a List’s elements must be comparable.
* To be searched, an array or List must first be sorted.
Utility Classes: Collections and Arrays
* Both of these java.util classes provide
* A sort() method. Sort using a Comparator or sort using natural order.
* A binarySearch() method. Search a pre-sorted array or List.
* Arrays.asList() creates a List from an array and links them together.
* Collections.reverse() reverses the order of elements in a List.
* Collections.reverseOrder() returns a Comparator that sorts in reverse.
* Lists and Sets have a toArray() method to create arrays.
Generics
* Generics let you enforce compile-time type safety on Collections (or other classes and methods declared using generic type parameters).
* An ArrayList< Car > can accept references of type Ferrari, Bmw, or any other subtype of Car
* When using generic collections, a cast is not needed to get (declared type) elements out of the collection. With non-generic collections, a cast is required:
List< String > gList = new ArrayList< String >();
List list = new ArrayList();
// more code
String s = gList.get(0); // no cast needed
String s = (String)list.get(0); // cast required
* You can pass a generic collection into a method that takes a non-generic collection, but the results may be disastrous. The compiler can’t stop the method from inserting the wrong type into the previously type safe collection.
* If the compiler can recognize that non-type-safe code is potentially endangering something you originally declared as type-safe, you will get a compiler warning. For instance, if you pass a List< String > into a method declared as
void foo(List aList) { aList.add(anInteger); }
* You’ll get a warning because add() is potentially “unsafe”.
* “Compiles without error” is not the same as “compiles without warnings.” A compilation warning is not considered a compilation error or failure.
* Generic type information does not exist at runtime—it is for compile-time safety only. Mixing generics with legacy code can create compiled code that may throw an exception at runtime.
* Polymorphic assignments applies only to the base type, not the generic type parameter. You can say
List< Car > aList = new ArrayList< Car >(); // yes
You can’t say
List< Car > aList = new ArrayList< Ferrari >(); // no
* The polymorphic assignment rule applies everywhere an assignment can be made. The following are NOT allowed:
void foo(List< Car > aList) { } // cannot take a List
List< Car > bar() { } // cannot return a List
* Wildcard syntax allows a generic method, accept subtypes (or supertypes) of the declared type of the method argument:
void addD(List< Car > d) {} // can take only < Car >
void addD(List< ? extends Car >) {} // take a < Car > or < Ferrari >
* The wildcard keyword extends is used to mean either “extends” or “implements.” So in extends Car>, Car can be a class or an interface.
* When using a wildcard, List< ? extends Car >, the collection can be accessed but not modified.
* When using a wildcard, List< ? >, any generic type can be assigned to the reference, but for access only, no modifications.
* List< Object > refers only to a List< Object >, while List< ? > or List< ? extends Object > can hold any type of object, but for access only.
* Declaration conventions for generics use T for type and E for element:
public interface List< E > // API declaration for List
boolean add(E o) // List.add() declaration
* The generics type identifier can be used in class, method, and variable declarations:
class Foo
T anInstance; // an instance variable
Foo(T aRef) {} // a constructor argument
void bar(T aRef) {} // a method argument
T baz() {} // a return type
The compiler will substitute the actual type.
* You can use more than one parameterized type in a declaration:
public class UseTwo
* You can declare a generic method using a type not defined in the class:
public
is NOT using T as the return type. This method has a void return type, but to use T within the method’s argument you must declare the
Previous Chapter: Chapter 51 - Generics
Next Chapter: Self Test - Chapters 38 to 51
Labels:
arraylist,
collection generics,
collections,
collection types,
different types of collections,
generics,
quick recap,
sorting collections,
using collections,
vector
| Reactions: |
Saturday, February 19, 2011
Quick Review: Chapters 32 to 37
Using String, StringBuffer, and StringBuilder
* String objects are immutable, and String reference variables are not.
* If you create a new String without assigning it, it will be lost to your program.
* If you redirect a String reference to a new String, the old String can be lost.
* String methods use zero-based indexes, except for the second argument of substring().
* The String class is final—its methods can’t be overridden.
* When the JVM finds a String literal, it is added to the String literal pool.
* Strings have a method: length(); arrays have an attribute named length.
* The StringBuffer’s API is the same as the new StringBuilder’s API, except that StringBuilder’s methods are not synchronized for thread safety.
* StringBuilder methods should run faster than StringBuffer methods.
All of the following bullets apply to both StringBuffer and StringBuilder:
* They are mutable—they can change without creating a new object.
* StringBuffer methods act on the invoking object, and objects can change without an explicit assignment in the statement.
* StringBuffer equals() is not overridden; it doesn’t compare values.
* Remember that chained methods are evaluated from left to right.
* String methods to remember: charAt(), concat(), equalsIgnoreCase(), length(), replace(), substring(), toLowerCase(), toString(), toUpperCase(), and trim().
* StringBuffer methods to remember: append(), delete(), insert(), reverse(), and toString().
File I/O
* The classes you need to understand in java.io are File, FileReader, BufferedReader, FileWriter, BufferedWriter, PrintWriter, and Console.
* A new File object doesn’t mean there’s a new file on your hard drive.
* File objects can represent either a file or a directory.
* The File class lets you manage (add, rename, and delete) files and directories.
* The methods createNewFile() and mkdir() add entries to your file system.
* FileWriter and FileReader are low-level I/O classes. You can use them to write and read files, but they should usually be wrapped.
* Classes in java.io are designed to be “chained” or “wrapped.” (This is a common use of the decorator design pattern.)
* It’s very common to “wrap” a BufferedReader around a FileReader or a BufferedWriter around a FileWriter, to get access to higher-level (more convenient) methods.
* PrintWriters can be used to wrap other Writers, but as of Java 5 they can be built directly from Files or Strings.
* Java 5 PrintWriters have new append(), format(), and printf() methods.
* Console objects can read non-echoed input and are instantiated using System.console().
Serialization
* The classes you need to understand are all in the java.io package; they include: ObjectOutputStream and ObjectInputStream primarily, and FileOutputStream and FileInputStream because you will use them to create the low-level streams that the ObjectXxxStream classes will use.
* A class must implement Serializable before its objects can be serialized.
* The ObjectOutputStream.writeObject() method serializes objects, and the ObjectInputStream.readObject() method deserializes objects.
* If you mark an instance variable transient, it will not be serialized even thought the rest of the object’s state will be.
* You can supplement a class’s automatic serialization process by implementing the writeObject() and readObject() methods. If you do this, embedding calls to defaultWriteObject() and defaultReadObject(), respectively, will handle the part of serialization that happens normally.
* If a superclass implements Serializable, then its subclasses do automatically.
* If a superclass doesn’t implement Serializable, then when a subclass object is deserialized, the superclass constructor will be invoked, along with its superconstructor(s).
Dates, Numbers, and Currency
* The classes you need to understand are java.util.Date, java.util.Calendar, java.text.DateFormat, java.text.NumberFormat, and java.util.Locale.
* Most of the Date class’s methods have been deprecated.
* A Date is stored as a long, the number of milliseconds since January 1, 1970.
* Date objects are go-betweens the Calendar and Locale classes.
* The Calendar provides a powerful set of methods to manipulate dates, performing tasks such as getting days of the week, or adding some number of months or years (or other increments) to a date.
* Create Calendar instances using static factory methods (getInstance()).
* The Calendar methods you should understand are add(), which allows you to add or subtract various pieces (minutes, days, years, and so on) of dates, and roll(), which works like add() but doesn’t increment a date’s bigger pieces.
* DateFormat instances are created using static factory methods (getInstance() and getDateInstance()).
* There are several format “styles” available in the DateFormat class.
* DateFormat styles can be applied against various Locales to create a wide array of outputs for any given date.
* The DateFormat.format() method is used to create Strings containing properly formatted dates.
* The Locale class is used in conjunction with DateFormat and NumberFormat.
* Both DateFormat and NumberFormat objects can be constructed with a specific, immutable Locale.
* For the exam you should understand creating Locales using language, or a combination of language and country.
Parsing, Tokenizing, and Formatting
* regex is short for regular expressions, which are the patterns used to search for data within large data sources.
* regex is a sub-language that exists in Java and other languages (such as Perl).
* regex lets you to create search patterns using literal characters or metacharacters. Metacharacters allow you to search for slightly more abstract data like “digits” or “whitespace”.
* Study the \d, \s, \w, and . metacharacters
* regex provides for quantifiers which allow you to specify concepts like: “look for one or more digits in a row.”
* Study the ?, *, and + greedy quantifiers.
* Remember that metacharacters and Strings don’t mix well unless you remember to “escape” them properly. For instance String s = "\\d";
* The Pattern and Matcher classes have Java’s most powerful regex capabilities.
* You should understand the Pattern compile() method and the Matcher matches(), pattern(), find(), start(), and group() methods.
* You WON’T need to understand Matcher’s replacement-oriented methods.
* You can use java.util.Scanner to do simple regex searches, but it is primarily intended for tokenizing.
* Tokenizing is the process of splitting delimited data into small pieces.
* In tokenizing, the data you want is called tokens, and the strings that separate the tokens are called delimiters.
* Tokenizing can be done with the Scanner class, or with String.split().
* Delimiters are single characters like commas, or complex regex expressions.
* The Scanner class allows you to tokenize data from within a loop, which allows you to stop whenever you want to.
* The Scanner class allows you to tokenize Strings or streams or files.
* The String.split() method tokenizes the entire source data all at once, so large amounts of data can be quite slow to process.
* New to Java 5 are two methods used to format data for output. These methods are format() and printf(). These methods are found in the PrintStream class, an instance of which is the out in System.out.
* The format() and printf() methods have identical functionality.
* Formatting data with printf() (or format()) is accomplished using formatting strings that are associated with primitive or string arguments.
* The format() method allows you to mix literals in with your format strings.
* The format string values you should know are
Flags: -, +, 0, “,”, and (
Conversions: b, c, d, f, and s
* If your conversion character doesn’t match your argument type, an exception will be thrown.
Previous Chapter: Chapter 37 - Searching, Parsing, Tokenizing and Formatting
Next Chapter: Self Test - Chapters 32 to 37
* String objects are immutable, and String reference variables are not.
* If you create a new String without assigning it, it will be lost to your program.
* If you redirect a String reference to a new String, the old String can be lost.
* String methods use zero-based indexes, except for the second argument of substring().
* The String class is final—its methods can’t be overridden.
* When the JVM finds a String literal, it is added to the String literal pool.
* Strings have a method: length(); arrays have an attribute named length.
* The StringBuffer’s API is the same as the new StringBuilder’s API, except that StringBuilder’s methods are not synchronized for thread safety.
* StringBuilder methods should run faster than StringBuffer methods.
All of the following bullets apply to both StringBuffer and StringBuilder:
* They are mutable—they can change without creating a new object.
* StringBuffer methods act on the invoking object, and objects can change without an explicit assignment in the statement.
* StringBuffer equals() is not overridden; it doesn’t compare values.
* Remember that chained methods are evaluated from left to right.
* String methods to remember: charAt(), concat(), equalsIgnoreCase(), length(), replace(), substring(), toLowerCase(), toString(), toUpperCase(), and trim().
* StringBuffer methods to remember: append(), delete(), insert(), reverse(), and toString().
File I/O
* The classes you need to understand in java.io are File, FileReader, BufferedReader, FileWriter, BufferedWriter, PrintWriter, and Console.
* A new File object doesn’t mean there’s a new file on your hard drive.
* File objects can represent either a file or a directory.
* The File class lets you manage (add, rename, and delete) files and directories.
* The methods createNewFile() and mkdir() add entries to your file system.
* FileWriter and FileReader are low-level I/O classes. You can use them to write and read files, but they should usually be wrapped.
* Classes in java.io are designed to be “chained” or “wrapped.” (This is a common use of the decorator design pattern.)
* It’s very common to “wrap” a BufferedReader around a FileReader or a BufferedWriter around a FileWriter, to get access to higher-level (more convenient) methods.
* PrintWriters can be used to wrap other Writers, but as of Java 5 they can be built directly from Files or Strings.
* Java 5 PrintWriters have new append(), format(), and printf() methods.
* Console objects can read non-echoed input and are instantiated using System.console().
Serialization
* The classes you need to understand are all in the java.io package; they include: ObjectOutputStream and ObjectInputStream primarily, and FileOutputStream and FileInputStream because you will use them to create the low-level streams that the ObjectXxxStream classes will use.
* A class must implement Serializable before its objects can be serialized.
* The ObjectOutputStream.writeObject() method serializes objects, and the ObjectInputStream.readObject() method deserializes objects.
* If you mark an instance variable transient, it will not be serialized even thought the rest of the object’s state will be.
* You can supplement a class’s automatic serialization process by implementing the writeObject() and readObject() methods. If you do this, embedding calls to defaultWriteObject() and defaultReadObject(), respectively, will handle the part of serialization that happens normally.
* If a superclass implements Serializable, then its subclasses do automatically.
* If a superclass doesn’t implement Serializable, then when a subclass object is deserialized, the superclass constructor will be invoked, along with its superconstructor(s).
Dates, Numbers, and Currency
* The classes you need to understand are java.util.Date, java.util.Calendar, java.text.DateFormat, java.text.NumberFormat, and java.util.Locale.
* Most of the Date class’s methods have been deprecated.
* A Date is stored as a long, the number of milliseconds since January 1, 1970.
* Date objects are go-betweens the Calendar and Locale classes.
* The Calendar provides a powerful set of methods to manipulate dates, performing tasks such as getting days of the week, or adding some number of months or years (or other increments) to a date.
* Create Calendar instances using static factory methods (getInstance()).
* The Calendar methods you should understand are add(), which allows you to add or subtract various pieces (minutes, days, years, and so on) of dates, and roll(), which works like add() but doesn’t increment a date’s bigger pieces.
* DateFormat instances are created using static factory methods (getInstance() and getDateInstance()).
* There are several format “styles” available in the DateFormat class.
* DateFormat styles can be applied against various Locales to create a wide array of outputs for any given date.
* The DateFormat.format() method is used to create Strings containing properly formatted dates.
* The Locale class is used in conjunction with DateFormat and NumberFormat.
* Both DateFormat and NumberFormat objects can be constructed with a specific, immutable Locale.
* For the exam you should understand creating Locales using language, or a combination of language and country.
Parsing, Tokenizing, and Formatting
* regex is short for regular expressions, which are the patterns used to search for data within large data sources.
* regex is a sub-language that exists in Java and other languages (such as Perl).
* regex lets you to create search patterns using literal characters or metacharacters. Metacharacters allow you to search for slightly more abstract data like “digits” or “whitespace”.
* Study the \d, \s, \w, and . metacharacters
* regex provides for quantifiers which allow you to specify concepts like: “look for one or more digits in a row.”
* Study the ?, *, and + greedy quantifiers.
* Remember that metacharacters and Strings don’t mix well unless you remember to “escape” them properly. For instance String s = "\\d";
* The Pattern and Matcher classes have Java’s most powerful regex capabilities.
* You should understand the Pattern compile() method and the Matcher matches(), pattern(), find(), start(), and group() methods.
* You WON’T need to understand Matcher’s replacement-oriented methods.
* You can use java.util.Scanner to do simple regex searches, but it is primarily intended for tokenizing.
* Tokenizing is the process of splitting delimited data into small pieces.
* In tokenizing, the data you want is called tokens, and the strings that separate the tokens are called delimiters.
* Tokenizing can be done with the Scanner class, or with String.split().
* Delimiters are single characters like commas, or complex regex expressions.
* The Scanner class allows you to tokenize data from within a loop, which allows you to stop whenever you want to.
* The Scanner class allows you to tokenize Strings or streams or files.
* The String.split() method tokenizes the entire source data all at once, so large amounts of data can be quite slow to process.
* New to Java 5 are two methods used to format data for output. These methods are format() and printf(). These methods are found in the PrintStream class, an instance of which is the out in System.out.
* The format() and printf() methods have identical functionality.
* Formatting data with printf() (or format()) is accomplished using formatting strings that are associated with primitive or string arguments.
* The format() method allows you to mix literals in with your format strings.
* The format string values you should know are
Flags: -, +, 0, “,”, and (
Conversions: b, c, d, f, and s
* If your conversion character doesn’t match your argument type, an exception will be thrown.
Previous Chapter: Chapter 37 - Searching, Parsing, Tokenizing and Formatting
Next Chapter: Self Test - Chapters 32 to 37
Labels:
calendar,
dates,
file,
filereader,
filewriter,
java scjp,
parsing,
quick recap,
SCJP,
SCJP Certification,
string formatting
| Reactions: |
Monday, February 14, 2011
Quick Review: Chapters 27 to 31
In the preceding 5 chapters we took a look at loops, logical condition blocks, exception handling and assertions. Lets quickly review what we have learnt in these chapters.
Writing Code Using if and switch Statements
* The only legal expression in an if statement is a boolean expression, in other words an expression that resolves to a boolean or a Boolean variable.
* Watch out for boolean assignments (=) that can be mistaken for boolean equality (==) tests:
boolean x = false;
if (x = true) { } // an assignment, so x will always be true!
* Curly braces are optional for if blocks that have only one conditional statement. But watch out for misleading indentations.
* switch statements can evaluate only to enums or the byte, short, int, and char data types. You can’t say,
long s = 30;
switch(s) { }
* The case constant must be a literal or final variable, or a constant expression, including an enum. You cannot have a case that includes a non-final variable, or a range of values.
* If the condition in a switch statement matches a case constant, execution will run through all code in the switch following the matching case statement until a break statement or the end of the switch statement is encountered. In other words, the matching case is just the entry point into the case block, but unless there’s a break statement, the matching case is not the only case code that runs.
* The default keyword should be used in a switch statement if you want to run some code when none of the case values match the conditional value.
* The default block can be located anywhere in the switch block, so if no case matches, the default block will be entered, and if the default does not contain a break, then code will continue to execute (fall-through) to the end of the switch or until the break statement is encountered.
Writing Code Using Loops
* A basic for statement has three parts: declaration and/or initialization, boolean evaluation, and the iteration expression.
* If a variable is incremented or evaluated within a basic for loop, it must be declared before the loop, or within the for loop declaration.
* A variable declared (not just initialized) within the basic for loop declaration cannot be accessed outside the for loop (in other words, code below the for loop won’t be able to use the variable).
* You can initialize more than one variable of the same type in the first part of the basic for loop declaration; each initialization must be separated by a comma.
* An enhanced for loop has two parts, the declaration and the expression. It is used only to loop through arrays or collections.
* With an enhanced for, the expression is the array or collection through which you want to loop.
* With an enhanced for, the declaration is the block variable, whose type is compatible with the elements of the array or collection, and that variable contains the value of the element for the given iteration.
* You cannot use a number (old C-style language construct) or anything that does not evaluate to a boolean value as a condition for an if statement or looping construct. You can’t, for example, say if(x), unless x is a boolean variable.
* The do loop will enter the body of the loop at least once, even if the test condition is not met.
Using break and continue
* An unlabeled break statement will cause the current iteration of the inner most looping construct to stop and the line of code following the loop to run.
* An unlabeled continue statement will cause: the current iteration of the innermost loop to stop, the condition of that loop to be checked, and if the condition is met, the loop to run again.
* If the break statement or the continue statement is labeled, it will cause similar action to occur on the labeled loop, not the innermost loop.
Handling Exceptions
* Exceptions come in two flavors: checked and unchecked.
* Checked exceptions include all subtypes of Exception, excluding classes that extend RuntimeException.
* Checked exceptions are subject to the handle or declare rule; any method that might throw a checked exception (including methods that invoke methods that can throw a checked exception) must either declare the exception using throws, or handle the exception with an appropriate try/catch.
* Subtypes of Error or RuntimeException are unchecked, so the compiler doesn’t enforce the handle or declare rule. You’re free to handle them, or to declare them, but the compiler doesn’t care one way or the other.
* If you use an optional finally block, it will always be invoked, regardless of whether an exception in the corresponding try is thrown or not, and regardless of whether a thrown exception is caught or not.
* The only exception to the finally-will-always-be-called rule is that a finally will not be invoked if the JVM shuts down. That could happen if code from the try or catch blocks calls System.exit().
* Just because finally is invoked does not mean it will complete. Code in the finally block could itself raise an exception or issue a System.exit().
* Uncaught exceptions propagate back through the call stack, starting from the method where the exception is thrown and ending with either the first method that has a corresponding catch for that exception type or a JVM shutdown (which happens if the exception gets to main(), and main() is “ducking” the exception by declaring it).
* You can create your own exceptions, normally by extending Exception or one of its subtypes. Your exception will then be considered a checked exception, and the compiler will enforce the handle or declare rule for that exception.
* All catch blocks must be ordered from most specific to most general. If you have a catch clause for both IOException and Exception, you must put the catch for IOException first in your code. Otherwise, the IOException would be caught by catch(Exception e), because a catch argument can catch the specified exception or any of its subtypes! The compiler will stop you from defining catch clauses that can never be reached.
* Some exceptions are created by programmers, some by the JVM.
Assertions
* Assertions give you a way to test your assumptions during development and debugging.
* Assertions are typically enabled during testing but disabled during deployment.
* You can use assert as a keyword (as of version 1.4) or an identifier, but not both together. To compile older code that uses assert as an identifier (for example, a method name), use the -source 1.3 command-line flag to javac.
* Assertions are disabled at runtime by default. To enable them, use a command-line flag -ea or -enableassertions.
* Selectively disable assertions by using the -da or -disableassertions flag.
* If you enable or disable assertions using the flag without any arguments, you’re enabling or disabling assertions in general. You can combine enabling and disabling switches to have assertions enabled for some classes and/or packages, but not others.
* You can enable and disable assertions on a class-by-class basis, using the following syntax:
java -ea -da:MyClass TestClass
* You can enable and disable assertions on a package-by-package basis, and any package you specify also includes any subpackages (packages further down the directory hierarchy).
* Do not use assertions to validate arguments to public methods.
* Do not use assert expressions that cause side effects. Assertions aren’t guaranteed to always run, and you don’t want behavior that changes depending on whether assertions are enabled.
* Do use assertions—even in public methods—to validate that a particular code block will never be reached. You can use assert false; for code that should never be reached, so that an assertion error is thrown immediately if the assert statement is executed.
Previous Chapter: Chapter 31 - Assertions
Next Chapter: Self Test - Chapters 27 to 31
Writing Code Using if and switch Statements
* The only legal expression in an if statement is a boolean expression, in other words an expression that resolves to a boolean or a Boolean variable.
* Watch out for boolean assignments (=) that can be mistaken for boolean equality (==) tests:
boolean x = false;
if (x = true) { } // an assignment, so x will always be true!
* Curly braces are optional for if blocks that have only one conditional statement. But watch out for misleading indentations.
* switch statements can evaluate only to enums or the byte, short, int, and char data types. You can’t say,
long s = 30;
switch(s) { }
* The case constant must be a literal or final variable, or a constant expression, including an enum. You cannot have a case that includes a non-final variable, or a range of values.
* If the condition in a switch statement matches a case constant, execution will run through all code in the switch following the matching case statement until a break statement or the end of the switch statement is encountered. In other words, the matching case is just the entry point into the case block, but unless there’s a break statement, the matching case is not the only case code that runs.
* The default keyword should be used in a switch statement if you want to run some code when none of the case values match the conditional value.
* The default block can be located anywhere in the switch block, so if no case matches, the default block will be entered, and if the default does not contain a break, then code will continue to execute (fall-through) to the end of the switch or until the break statement is encountered.
Writing Code Using Loops
* A basic for statement has three parts: declaration and/or initialization, boolean evaluation, and the iteration expression.
* If a variable is incremented or evaluated within a basic for loop, it must be declared before the loop, or within the for loop declaration.
* A variable declared (not just initialized) within the basic for loop declaration cannot be accessed outside the for loop (in other words, code below the for loop won’t be able to use the variable).
* You can initialize more than one variable of the same type in the first part of the basic for loop declaration; each initialization must be separated by a comma.
* An enhanced for loop has two parts, the declaration and the expression. It is used only to loop through arrays or collections.
* With an enhanced for, the expression is the array or collection through which you want to loop.
* With an enhanced for, the declaration is the block variable, whose type is compatible with the elements of the array or collection, and that variable contains the value of the element for the given iteration.
* You cannot use a number (old C-style language construct) or anything that does not evaluate to a boolean value as a condition for an if statement or looping construct. You can’t, for example, say if(x), unless x is a boolean variable.
* The do loop will enter the body of the loop at least once, even if the test condition is not met.
Using break and continue
* An unlabeled break statement will cause the current iteration of the inner most looping construct to stop and the line of code following the loop to run.
* An unlabeled continue statement will cause: the current iteration of the innermost loop to stop, the condition of that loop to be checked, and if the condition is met, the loop to run again.
* If the break statement or the continue statement is labeled, it will cause similar action to occur on the labeled loop, not the innermost loop.
Handling Exceptions
* Exceptions come in two flavors: checked and unchecked.
* Checked exceptions include all subtypes of Exception, excluding classes that extend RuntimeException.
* Checked exceptions are subject to the handle or declare rule; any method that might throw a checked exception (including methods that invoke methods that can throw a checked exception) must either declare the exception using throws, or handle the exception with an appropriate try/catch.
* Subtypes of Error or RuntimeException are unchecked, so the compiler doesn’t enforce the handle or declare rule. You’re free to handle them, or to declare them, but the compiler doesn’t care one way or the other.
* If you use an optional finally block, it will always be invoked, regardless of whether an exception in the corresponding try is thrown or not, and regardless of whether a thrown exception is caught or not.
* The only exception to the finally-will-always-be-called rule is that a finally will not be invoked if the JVM shuts down. That could happen if code from the try or catch blocks calls System.exit().
* Just because finally is invoked does not mean it will complete. Code in the finally block could itself raise an exception or issue a System.exit().
* Uncaught exceptions propagate back through the call stack, starting from the method where the exception is thrown and ending with either the first method that has a corresponding catch for that exception type or a JVM shutdown (which happens if the exception gets to main(), and main() is “ducking” the exception by declaring it).
* You can create your own exceptions, normally by extending Exception or one of its subtypes. Your exception will then be considered a checked exception, and the compiler will enforce the handle or declare rule for that exception.
* All catch blocks must be ordered from most specific to most general. If you have a catch clause for both IOException and Exception, you must put the catch for IOException first in your code. Otherwise, the IOException would be caught by catch(Exception e), because a catch argument can catch the specified exception or any of its subtypes! The compiler will stop you from defining catch clauses that can never be reached.
* Some exceptions are created by programmers, some by the JVM.
Assertions
* Assertions give you a way to test your assumptions during development and debugging.
* Assertions are typically enabled during testing but disabled during deployment.
* You can use assert as a keyword (as of version 1.4) or an identifier, but not both together. To compile older code that uses assert as an identifier (for example, a method name), use the -source 1.3 command-line flag to javac.
* Assertions are disabled at runtime by default. To enable them, use a command-line flag -ea or -enableassertions.
* Selectively disable assertions by using the -da or -disableassertions flag.
* If you enable or disable assertions using the flag without any arguments, you’re enabling or disabling assertions in general. You can combine enabling and disabling switches to have assertions enabled for some classes and/or packages, but not others.
* You can enable and disable assertions on a class-by-class basis, using the following syntax:
java -ea -da:MyClass TestClass
* You can enable and disable assertions on a package-by-package basis, and any package you specify also includes any subpackages (packages further down the directory hierarchy).
* Do not use assertions to validate arguments to public methods.
* Do not use assert expressions that cause side effects. Assertions aren’t guaranteed to always run, and you don’t want behavior that changes depending on whether assertions are enabled.
* Do use assertions—even in public methods—to validate that a particular code block will never be reached. You can use assert false; for code that should never be reached, so that an assertion error is thrown immediately if the assert statement is executed.
Previous Chapter: Chapter 31 - Assertions
Next Chapter: Self Test - Chapters 27 to 31
| Reactions: |
Friday, February 4, 2011
Quick Review - Chapters 22 to 26
Below is a review of the most important points that were covered in the previous Chapters
Relational Operators
* Relational operators always result in a boolean value (true or false).
* There are six relational operators: >, >=, <, <=, ==, and !=. The last two (== and !=) are sometimes referred to as equality operators. * When comparing characters, Java uses the Unicode value of the character as the numerical value. * Equality operators - There are two equality operators: == and !=. - Four types of things can be tested: numbers, characters, booleans, and reference variables.
* When comparing reference variables, == returns true only if both references refer to the same object.
instanceof Operator
* instanceof is for reference variables only, and checks for whether the object is of a particular type.
* The instanceof operator can be used only to test objects (or null) against class types that are in the same class hierarchy.
* For interfaces, an object passes the instanceof test if any of its superclasses implement the interface on the right side of the instanceof operator.
Arithmetic Operators
* There are four primary math operators: add, subtract, multiply, and divide.
* The remainder operator (%), returns the remainder of a division.
* Expressions are evaluated from left to right, unless you add parentheses, or unless some operators in the expression have higher precedence than others.
* The *, /, and % operators have higher precedence than + and -.
String Concatenation Operator
* If either operand is a String, the + operator concatenates the operands.
* If both operands are numeric, the + operator adds the operands.
Increment/Decrement Operators
* Prefix operators (++ and --) run before the value is used in the expression.
* Postfix operators (++ and --) run after the value is used in the expression.
* In any expression, both operands are fully evaluated before the operator is applied.
* Variables marked final cannot be incremented or decremented.
Ternary (Conditional Operator)
* Returns one of two values based on whether a boolean expression is true or false.
- Returns the value after the ? if the expression is true.
- Returns the value after the : if the expression is false.
Logical Operators
* The exam covers six “logical” operators: &, |, ^, !, &&, and ||.
* Logical operators work with two expressions (except for !) that must resolve to boolean values.
* The && and & operators return true only if both operands are true.
* The || and | operators return true if either or both operands are true.
* The && and || operators are known as short-circuit operators.
* The && operator does not evaluate the right operand if the left operand is false.
* The || does not evaluate the right operand if the left operand is true.
* The & and | operators always evaluate both operands.
* The ^ operator (called the “logical XOR”), returns true if exactly one operand is true.
* The ! operator (called the “inversion” operator), returns the opposite value of the boolean operand it precedes.
Previous Chapter: Chapter 26 - Logical Operators
Next Chapter: Self Test - Chapters 22 to 26
Relational Operators
* Relational operators always result in a boolean value (true or false).
* There are six relational operators: >, >=, <, <=, ==, and !=. The last two (== and !=) are sometimes referred to as equality operators. * When comparing characters, Java uses the Unicode value of the character as the numerical value. * Equality operators - There are two equality operators: == and !=. - Four types of things can be tested: numbers, characters, booleans, and reference variables.
* When comparing reference variables, == returns true only if both references refer to the same object.
instanceof Operator
* instanceof is for reference variables only, and checks for whether the object is of a particular type.
* The instanceof operator can be used only to test objects (or null) against class types that are in the same class hierarchy.
* For interfaces, an object passes the instanceof test if any of its superclasses implement the interface on the right side of the instanceof operator.
Arithmetic Operators
* There are four primary math operators: add, subtract, multiply, and divide.
* The remainder operator (%), returns the remainder of a division.
* Expressions are evaluated from left to right, unless you add parentheses, or unless some operators in the expression have higher precedence than others.
* The *, /, and % operators have higher precedence than + and -.
String Concatenation Operator
* If either operand is a String, the + operator concatenates the operands.
* If both operands are numeric, the + operator adds the operands.
Increment/Decrement Operators
* Prefix operators (++ and --) run before the value is used in the expression.
* Postfix operators (++ and --) run after the value is used in the expression.
* In any expression, both operands are fully evaluated before the operator is applied.
* Variables marked final cannot be incremented or decremented.
Ternary (Conditional Operator)
* Returns one of two values based on whether a boolean expression is true or false.
- Returns the value after the ? if the expression is true.
- Returns the value after the : if the expression is false.
Logical Operators
* The exam covers six “logical” operators: &, |, ^, !, &&, and ||.
* Logical operators work with two expressions (except for !) that must resolve to boolean values.
* The && and & operators return true only if both operands are true.
* The || and | operators return true if either or both operands are true.
* The && and || operators are known as short-circuit operators.
* The && operator does not evaluate the right operand if the left operand is false.
* The || does not evaluate the right operand if the left operand is true.
* The & and | operators always evaluate both operands.
* The ^ operator (called the “logical XOR”), returns true if exactly one operand is true.
* The ! operator (called the “inversion” operator), returns the opposite value of the boolean operand it precedes.
Previous Chapter: Chapter 26 - Logical Operators
Next Chapter: Self Test - Chapters 22 to 26
Labels:
arithmetic operator,
decrement,
increment,
instanceof operator,
logical operators,
quick recap,
relational operators,
ternary operator
| Reactions: |
Monday, January 3, 2011
Quick Recap – Chapters 1 to 5
We have successfully completed 5 chapters in our preparation towards the SCJP certification preparation. Let us do a quick recap to cover what we have seen so far.
Chapter 1:
We saw that classes are the backbone based on which the java programming language revolves and everything in java is an Object (Java is an object oriented language)
• A class is like a template that describes the kinds of state and behavior that a particular object will support
• A class contains variables that refer to the objects state and methods that describe the behavior a class is expected to portray
• Java programs run on the Java Virtual Machine (JVM)
• Keywords are predefined words in the java language that tell the JVM to perform a predefined action
• You cannot use keywords are names for your variables or methods
Chapter 2:
We covered the declaration of various java entities like classes, interfaces etc in this chapter.
Java Source Files
• There can be only one public class per source file (a .java extension file)
• If there is a public class in a file, then the file name should be the name of the public class with a .java extension
• The package statement should always be the first statement in a java source file
• A file can have more than one non-public class
Class & Interface Declaration:
• A class can be created by using the “class” keyword
• The different types of classes we can create are final, abstract and the normal java classes
• An abstract class is a special kind of class that cannot be instantiated
• Any class that has one or more abstract methods has to be declared abstract
• An Interface defines a contract of what a class can do without saying anything about the exact implementation
• Any class that implements an interface has to provide implementation (code) for all the methods in the interface
• An interface is an 100% abstract class
• Variables in an interface are by default static and final which means they are constants
• An interface or an abstract cannot have final methods
• Every class has atleast one constructor that would get invoked during the process of object creation of the class
• If you don’t write a constructor, the compiler will build a default no-arg constructor for you
• Constructors cannot be abstract, static or final
Declaring Variables:
• There are two types of variables in Java – Primitives and Reference variables
• Static variables belong to the class and not to any object instance
• Variables declared inside methods are called local variables whereas ones declared inside a class (outside of any methods) are called instance variables
• Arrays are objects that hold multiple variables of the same type
• Though arrays are useful, collections like ArrayList or Vector provide more functionality than normal arrays
JavaBean Naming Conventions:
This is something I should have covered in the Declarations chapter. Since it is very small I thought I will add it to the quick re-cap chapter.
• All class names should start with a Capital letter and should follow camel case. Ex: TestStaticClass (See the capitalization of subsequent words)
• All method names should start with a small letter and should follow camel case. Ex: getNameOfEmployee()
• Method names should contain a prefix that gives an indication of what the method is supposed to do
• “get” is used usually for methods that return a particular value like getName() or getAge() etc
• “set” or “put” is used usually for methods that are used to modify the value like setName() or putDepositMoney() etc
• Methods that check a Boolean value must be prefixed with “is” like isTrue() or isValid() etc
• “add” is a keyword that is used usually with adding listeners to UI components like addEventListener() etc
Chapter 3:
In this chapter we had a detailed look at enumerations.
• enums can be used to refer to pre-defined values (constants) for your java program
• It is a good practice to have your enums in all CAPS to let other programmers know that they are constants
• enums cannot be declared inside methods
• Every enum has a static method, values(), that returns an array of the enum’s values in the order they’re declared
Chapter 4:
In this chapter we looked at the various Access Modifiers in java. They are public, private, protected and the default (no keyword) access modifiers.
• public is the least restrictive modifier whereas private is the most restrictive
• Though you may feel that public is better because all other classes can access your methods, that is seldom the case because a code that is visible to all other classes is not secure and that is not the best way to write your code. It is always best to provide just the appropriate level of access to methods and variables instead of having all of them public
• Protected and default access behave the same way as long as inheritance is not involved
• You cannot apply access modifiers to local variables
Chapter 5:
In this chapter we looked at the Non-Access Modifiers, the modifiers that do not alter the accessibility of java class members but that do alter its behavior.
• strictfp ensures that the floating point calculations in your code is in accordance to the IEEE 754 guidelines
• final classes cannot be inherited (sub-classed or extended)
• All java’s core library classes (ex: java.lang.String) are final
• An abstract class can never be instantiated
• A class cannot be both abstract and final
• Final methods cannot be overridden by any sub-class that might extend the original class
• Abstract methods have to be implemented (overridden) by the sub-class that extends the original class
• A method cannot be both abstract and final
• A synchronized method can be executed by only one thread at any time
• A native method is one which is implemented in a language that is not java (usually C)
• Static methods belong to a class and not any object instance of a class
• Static methods can call/invoke only other static methods/variables
• Final variables cannot be modified once they are assigned an initial value (not the default value)
• Transient variables will not be serialized when the object is serialized
• Using volatile keyword for variables in a multi-threaded application is a bad idea
• Static variables belong to a class and no matter how many objects you create of that class, there will be only one instance of the static variable
• Method arguments can be declared final which ensures that those variables will not be modified inside the method code
That rounds up the quick recap of the first 5 chapters of this SCJP series.
Previous Chapter: Chapter 5
Next Chapter: Self Test Chapters 1 to 5
Tip: You can bookmark this page (and the other quick recaps) to refresh just before your exam.
Chapter 1:
We saw that classes are the backbone based on which the java programming language revolves and everything in java is an Object (Java is an object oriented language)
• A class is like a template that describes the kinds of state and behavior that a particular object will support
• A class contains variables that refer to the objects state and methods that describe the behavior a class is expected to portray
• Java programs run on the Java Virtual Machine (JVM)
• Keywords are predefined words in the java language that tell the JVM to perform a predefined action
• You cannot use keywords are names for your variables or methods
Chapter 2:
We covered the declaration of various java entities like classes, interfaces etc in this chapter.
Java Source Files
• There can be only one public class per source file (a .java extension file)
• If there is a public class in a file, then the file name should be the name of the public class with a .java extension
• The package statement should always be the first statement in a java source file
• A file can have more than one non-public class
Class & Interface Declaration:
• A class can be created by using the “class” keyword
• The different types of classes we can create are final, abstract and the normal java classes
• An abstract class is a special kind of class that cannot be instantiated
• Any class that has one or more abstract methods has to be declared abstract
• An Interface defines a contract of what a class can do without saying anything about the exact implementation
• Any class that implements an interface has to provide implementation (code) for all the methods in the interface
• An interface is an 100% abstract class
• Variables in an interface are by default static and final which means they are constants
• An interface or an abstract cannot have final methods
• Every class has atleast one constructor that would get invoked during the process of object creation of the class
• If you don’t write a constructor, the compiler will build a default no-arg constructor for you
• Constructors cannot be abstract, static or final
Declaring Variables:
• There are two types of variables in Java – Primitives and Reference variables
• Static variables belong to the class and not to any object instance
• Variables declared inside methods are called local variables whereas ones declared inside a class (outside of any methods) are called instance variables
• Arrays are objects that hold multiple variables of the same type
• Though arrays are useful, collections like ArrayList or Vector provide more functionality than normal arrays
JavaBean Naming Conventions:
This is something I should have covered in the Declarations chapter. Since it is very small I thought I will add it to the quick re-cap chapter.
• All class names should start with a Capital letter and should follow camel case. Ex: TestStaticClass (See the capitalization of subsequent words)
• All method names should start with a small letter and should follow camel case. Ex: getNameOfEmployee()
• Method names should contain a prefix that gives an indication of what the method is supposed to do
• “get” is used usually for methods that return a particular value like getName() or getAge() etc
• “set” or “put” is used usually for methods that are used to modify the value like setName() or putDepositMoney() etc
• Methods that check a Boolean value must be prefixed with “is” like isTrue() or isValid() etc
• “add” is a keyword that is used usually with adding listeners to UI components like addEventListener() etc
Chapter 3:
In this chapter we had a detailed look at enumerations.
• enums can be used to refer to pre-defined values (constants) for your java program
• It is a good practice to have your enums in all CAPS to let other programmers know that they are constants
• enums cannot be declared inside methods
• Every enum has a static method, values(), that returns an array of the enum’s values in the order they’re declared
Chapter 4:
In this chapter we looked at the various Access Modifiers in java. They are public, private, protected and the default (no keyword) access modifiers.
• public is the least restrictive modifier whereas private is the most restrictive
• Though you may feel that public is better because all other classes can access your methods, that is seldom the case because a code that is visible to all other classes is not secure and that is not the best way to write your code. It is always best to provide just the appropriate level of access to methods and variables instead of having all of them public
• Protected and default access behave the same way as long as inheritance is not involved
• You cannot apply access modifiers to local variables
Chapter 5:
In this chapter we looked at the Non-Access Modifiers, the modifiers that do not alter the accessibility of java class members but that do alter its behavior.
• strictfp ensures that the floating point calculations in your code is in accordance to the IEEE 754 guidelines
• final classes cannot be inherited (sub-classed or extended)
• All java’s core library classes (ex: java.lang.String) are final
• An abstract class can never be instantiated
• A class cannot be both abstract and final
• Final methods cannot be overridden by any sub-class that might extend the original class
• Abstract methods have to be implemented (overridden) by the sub-class that extends the original class
• A method cannot be both abstract and final
• A synchronized method can be executed by only one thread at any time
• A native method is one which is implemented in a language that is not java (usually C)
• Static methods belong to a class and not any object instance of a class
• Static methods can call/invoke only other static methods/variables
• Final variables cannot be modified once they are assigned an initial value (not the default value)
• Transient variables will not be serialized when the object is serialized
• Using volatile keyword for variables in a multi-threaded application is a bad idea
• Static variables belong to a class and no matter how many objects you create of that class, there will be only one instance of the static variable
• Method arguments can be declared final which ensures that those variables will not be modified inside the method code
That rounds up the quick recap of the first 5 chapters of this SCJP series.
Previous Chapter: Chapter 5
Next Chapter: Self Test Chapters 1 to 5
Labels:
chapter review,
Java,
points to remember,
quick recap,
SCJP,
SCJP Certification
| Reactions: |
Subscribe to:
Posts (Atom)
© 2013 by www.inheritingjava.blogspot.com. All rights reserved. No part of this blog or its contents may be reproduced or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without prior written permission of the Author.
