IAC 2024 - IA Fast Track to Search Focused AI Solutions
Best practices in Java and Swing
1. Best practices in Java and Swing
Arne Bachmann
Folie 1
Vortrag > Autor > Dokumentname > 09.11.2005
2. Topics
Arrays, Collections and Loops
Enumerations
The final keyword
Threading
In Swing
Singleton
Tools
Folie 2
Vortrag > Autor > Dokumentname > 09.11.2005
3. Arrays, Collections and Loops
"Foreach" style loop
void listLines(String[] lines) {
PrintStream ps = new PrintStream(
new FileOutputStream("C:test.out"));
for (String line: lines) {
ps.println(line);
}
ps.close();
}
Folie 3
Vortrag > Autor > Dokumentname > 09.11.2005
4. Arrays, Collections and Loops
"Map-Entry" style loop – similar to ".items()" in Python
String listItems(Map<String, Long> collection) {
StringBuilder sb = new StringBuilder();
for (Entry<String, Long> entry: collection.entrySet())
{
sb.append(entry.getKey())
.append(" maps to ")
.append(entry.getValue());
.append("n");
}
return sb.toString();
}
Folie 4
Vortrag > Autor > Dokumentname > 09.11.2005
6. Enumerations
Don't try to serialize enums
don't provide a private static final long serialVersionUID
Use enum instead of true/false where possible
import static my.package.Visibility.VISIBLE;
import static my.package.Visibility.HIDDEN;
display.setVisible(VISIBLE);
display.setVisible(HIDDEN);
Folie 6
Vortrag > Autor > Dokumentname > 09.11.2005
7. Enumerations
Don't try to serialize enums
don't provide a private static final long serialVersionUID
Use enum instead of true/false where possible
import static my.package.Visibility.VISIBLE;
import static my.package.Visibility.HIDDEN;
Import static my.package.Visibility.SEMI_TRANSPARENT;
display.setVisible(SEMI_TRANSPARENT);
Folie 7
Vortrag > Autor > Dokumentname > 09.11.2005
8. Enumerations
Combine settings by using enumSet
enum ELogCapability {
Console,
Graphical,
File;
}
// Constructor
MyLogger(EnumSet<ELogCapability> logTypes) {
if (logTypes.contains(ELogCapability.Console))
{
// ...
} else if ...
}
Folie 8
Vortrag > Autor > Dokumentname > 09.11.2005
9. Enumerations
Powerful enumerations – Part 1: The less known constructor
enum EVariableDataType {
Integer ("long"),
Real ("double"),
File ("file");
private final String type;
private EVariableDataType(String aType) {
type = aType;
}
}
Folie 9
Vortrag > Autor > Dokumentname > 09.11.2005
10. Enumerations
Powerful enumerations – Part 2: The trick
private static final Map<String, EVariableDataType>
TYPES = new Hashtable<String, EVariableDataType>();
static {
TYPES.put(Integer.type, Integer);
TYPES.put(Real.type, Real);
TYPES.put(File.type, File);
}
public static EVariableDataType typeOf(String forName) {
return TYPES.get(forName.toLowerCase());
}
Folie 10
Vortrag > Autor > Dokumentname > 09.11.2005
11. Final
Folie 11
Vortrag > Autor > Dokumentname > 09.11.2005
12. Final
Use final as often as possible
final class ExampleClass {
void example(final File source) {
final File[] files = source.listFiles();
for (final File file: files) {
final String name =
file.getAbsolutePath();
try {
file.delete();
} catch (final IOException e) {
logger.error(e);
}
}
}
}
Folie 12
Vortrag > Autor > Dokumentname > 09.11.2005
13. Final
Constant value initialization from the constructor
protected class MyClass {
final private String param;
MyClass(final String p) {
param = p;
}
}
Folie 13
Vortrag > Autor > Dokumentname > 09.11.2005
14. Variable number of arguments
Beware of varargs methods:
Can create very hard to find errors
Long[] createLongArray(final long first) {
return new Long[] { first };
}
Long[] createLongArray(final long first, final long second) {
return new Long[] { first, second };
}
Long[] createLongArray(long... args) {
final List<Long> list = new ArrayList<Long>();
for (final Long l: args) {
list.add(l);
}
return list.toArray(new Long[0]); // or: new Long[] {}
}
Folie 14
Vortrag > Autor > Dokumentname > 09.11.2005
16. Collections
Always type collections (we're in Java SE 5, which already came 2004)
e.g.: List<Pair<String, Wrapper<ELogCapability>[]>> list;
Hashtable<T, U>
Allows only non-null keys and values
Synchronized
HashMap<T, U>
Allows null for both keys and values
Unsynchronized
Use new ConcurrentHashMap() for Collections.synchronizedMap()
Internally synchronized
Folie 16
Vortrag > Autor > Dokumentname > 09.11.2005
18. Singleton
Singleton – Often implemented wrong:
public class MySingleton {
private static MySingleton instance;
private MySingleton() {
// initialization
}
public static MySingleton getInstance() {
if (instance == null) {
instance = new MySingleton();
}
return instance;
}
}
Folie 18
Vortrag > Autor > Dokumentname > 09.11.2005
19. Singleton
Singleton – This works
public class MySingleton {
private static MySingleton instance;
private MySingleton() {
// initialization
}
public static synchronized MySingleton getInstance() {
if (instance == null) {
instance = new MySingleton();
}
return instance;
}
}
Folie 19
Vortrag > Autor > Dokumentname > 09.11.2005
20. Singleton
Singleton – Use synchronization of the classloader
public class MySingleton2 {
final static private MySingleton2 instance = new MySingleton2();
private MySingleton2() {
// initialization
}
public MySingleton2 getInstance() {
return instance;
}
}
Folie 20
Vortrag > Autor > Dokumentname > 09.11.2005
22. Threading
Useful: Set UncaughtExceptionHandler
class MyHandler implements UncaughtExceptionHandler {
public void uncaughtException(final Thread t, final Throwable e) {
logger.error(t.getName() + ": " + e.getMessage());
}
}
void newThread() {
final Thread thread = new Thread(new Runnable() {
public void run() {
// do something in the thread
}
});
thread.setUncaughtExceptionHandler(new MyHandler.getInstance());
}
Folie 22
Vortrag > Autor > Dokumentname > 09.11.2005
23. Threading
How to create standard threads
Dont' use new Thread(…) anymore!
final ExecutorService single;
single = Executors.newSingleThreadExecutor();
single.execute(new Runnable() {
public void run() {
// anonymous code
}
});
Folie 23
Vortrag > Autor > Dokumentname > 09.11.2005
24. Threading
How to create standard threads
Dont' use new Thread(…) anymore!
final ExecutorService single;
final ExecutorService pool;
final ExecutorService timed;
single = Executors.newSingleThreadExecutor();
pool = Executors.newFixedThreadPool(3);
timed = Executors.newSingleThreadScheduledExecutor();
single.execute(new Runnable() {
public void run() {
// anonymous code
}
});
Folie 24
Vortrag > Autor > Dokumentname > 09.11.2005
25. Threading
Use volatile and synchronize wisely
Not easy to understand, find yourself some articles on that topic!
Volatile ensures visibility of
Variable reference (for reference types)
Variable value (for simple types)
Use atomic types for long and double
Because Java usually doesn't guarantee visibility of other
threads' memory changes
Synchronize explicitly uses JVM's object locking mechanism to
synchronize (linearize) variable accesses → deadlocks possible
Folie 25
Vortrag > Autor > Dokumentname > 09.11.2005
26. Threading
Avoid using anonymous classes where applicable
Refactor to named classes step-by-step
How to avoid the "synthetic accessor method" problem?
Named inner classes, see next slide
Folie 26
Vortrag > Autor > Dokumentname > 09.11.2005
27. Threading
"Read access is emulated by a synthetic accessor" (Eclipse warning)
public class WrongSyntheticAccessorExample extends JDialog {
private String name;
protected JPanel createPanel() {
final JPanel panel = new JPanel();
final JButton button = new JButton("Huh?");
button.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent evt) {
button.setText(button.getText() + name);
}
});
return panel;
}
}
Folie 27
Vortrag > Autor > Dokumentname > 09.11.2005
28. Threading
Solution: Inner classes
public class SyntheticAccessorExample extends JDialog {
private class InnerClass implements ActionListener {
private final String copyOfName;
private final JButton buttonRef;
InnerClass(final String name, final JButton button) {
copyOfName = new String(name); // shallow clone
buttonRef = button; // keep reference
}
public void actionPerformed(final ActionEvent evt) {
buttonRef.setText(buttonRef.getText() + copyOfName);
}
}
protected JPanel createPanel() {
final JPanel panel = new JPanel();
final JButton button = new JButton("Huh?");
button.addActionListener(new InnerClass("Done!", button));
return panel;
}
}
Folie 28
Vortrag > Autor > Dokumentname > 09.11.2005
29. Threading in Swing
The Event Dispatch Thread (EDT)
Almost everything GUI related must happen in this thread!
Otherwise: GUI not updated, blocking or unintelligible results
Exception: first static call from main or init
Exception: repaint() … and listener (de-) registration
Events by GUI components are always automatically on the EDT
Put everything CPU or time consuming to other threads (executors)
And provide callbacks for GUI updates
Q: How to build up a complex GUI while staying responsive?
Folie 29
Vortrag > Autor > Dokumentname > 09.11.2005
30. Threading in Swing
Events by GUI components are always automatically on the EDT, e.g.
public void actionPerformed(final ActionEvent evt) {}
public void mouseClicked(final MouseEvent e) {}
Use javax.swing.Timer to create repeating events on the EDT:
final Timer timer = new Timer(200 /* ms */,
new ActionListener() {
public void actionPerformed(final ActionEvent evt) {
button.setEnabled(!button.isEnabled());
}
});
timer.setInitialDelay(0); // start immediately
timer.start();
Folie 30
Vortrag > Autor > Dokumentname > 09.11.2005
31. Threading in Swing
Put everything CPU or time consuming to other threads (executors)
And provide callbacks for GUI updates
final JButton okB = new JButton("OK");
okB.setEnabled(false);
final ExecutorService thread =
Executors.newSingleThreadExecutor();
thread.execute(new Runnable() {
public void run() {
// do some time-consuming calculations here
SwingUtilities.invokeLater(new Runnable() {
public void run() {
okB.setEnabled(true);
}
});
thread.shutdown(); // commence own shutdown
}
}); Folie 31
Vortrag > Autor > Dokumentname > 09.11.2005
32. Threading in Swing
Initialization during class load or construction is possible
OK if class loaded on EDT (e.g. new GUI(); in invokeLater())
OK if initialization is only simple, fast and failsafe
BUT if exceptions occur here, they are hard to track down!
Folie 32
Vortrag > Autor > Dokumentname > 09.11.2005
33. Threading in Swing
Question: How to build up a complex GUI while staying responsive?
A: Ensure that a splash screen is shown before building GUI?
A: Break down GUI creation into single work tasks queued in EDT?
A: Interrupt the thread somehow?
Folie 33
Vortrag > Autor > Dokumentname > 09.11.2005
34. Tools
VisualVM
Based on Netbeans platform
Connects to VMs via JMX (really useful only since Java SE 6)
Allows profiling, monitoring, recording, snapshotting
Many plugins available
Swing Explorer Library
Detect errors in UI applications
Folie 34
Vortrag > Autor > Dokumentname > 09.11.2005
35. References
Enumerations
http://www.javaworld.com/community/node/3125
Singleton
http://www.theserverside.de/singleton-pattern-in-java/
Threading
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html
Java Best practices:
Joshua Bloch (2008): "Effective Java. Second edition."
Folie 35
Vortrag > Autor > Dokumentname > 09.11.2005