📄 jan01_ericg.txt
字号:
J 2 M E T E C H T I P S
TIPS, TECHNIQUES, AND SAMPLE CODE
WELCOME to the Java Developer Connection(sm) (JDC)
Java(tm) 2 Platform, Micro Edition (J2ME(tm))
Tech Tips, for January 29, 2001. This issue covers:
* Writing World-Aware J2ME Applications
* Dealing With Missing J2SE Classes
The J2ME Tech Tips are written by Eric Giguere
(http://www.ericgiguere.com), an engineer at iAnywhere
Solutions, inc, and author of the book "Java 2 Micro
Edition: Professional Developer's Guide."
You can view this issue of the J2ME Tech Tips on the Web at
http://java.sun.com/jdc/J2METechTips/2001/tt0129.html
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
WRITING WORLD-AWARE J2ME APPLICATIONS
Well-written applications are both internationalized and
localized. An application is internationalized, if it can
correctly handle different encodings of character data. An
application is localized, if it formats and interprets data
(dates, times, timezones, currencies, messages and so on)
according to rules specific to the user's locale (country and
language). An application that is both internationalized and
localized, can be referred to as "world-aware."
Writing a world-aware application in the Java(tm) programming
language is easy enough with Java(tm) 2 Standard Edition
(J2SE(tm)). That's because of J2SE's extensive set of core Java
classes devoted to internationalization and localization. Refer
to the java.util.Calendar, java.util.Locale, java.text.Format,
and java.io.Reader classes for examples of this support.
However, writing a world-aware application that runs in the
stripped-down environment of J2ME can be a real challenge
because most of the J2SE support classes simply aren't in J2ME.
This is especially true for any J2ME implementation based on the
Connected Limited Device Configuration (CLDC) and its associated
profiles. CLDC includes a very small subset of J2SE core classes.
Still, it's not an impossible to write a world-aware J2ME
application, once you're aware of what's available and what's
not.
It's important to remember that with J2ME, memory is always at
a premium -- the device might have very little space available
for storing and running Java applications. Instead of bundling
your applications as a single JAR file that can run in multiple
locales, plan to create separate JARs for each locale. Include
in each JAR, only the classes and resources required by that
locale. The user can then download and install the version of
the application optimized for their own locale. Sometimes the
downloading can be automated. If a device can download
application JAR files using HTTP, a servlet on the web server
can be written to automatically send the appropriate JAR file
based on the locale information encoded in the HTTP headers.
In terms of support classes, the CLDC includes the following
J2SE classes:
java.io.DataInputStream
java.io.DataOutputStream
java.io.InputStreamReader
java.io.OutputStreamWriter
java.io.Reader
java.io.Writer
java.util.Calendar
java.util.Date
java.util.TimeZone
The InputStreamReader and OutputStreamReader classes are
particularly important because they convert raw byte streams
into Unicode-based character streams and back. The conversion
is done according to a particular character encoding system.
The default encoding for the platform is obtained from a system
property:
String encoding = System.getProperty( "microedition.encoding" );
At the very least, a CLDC implementation must support the
ISO8859_1 (Latin 1) encoding, but can optionally support other
encodings. For example, a Japanese implementation is likely to
support the SJIS (Shift-JIS) encoding.
The Calendar, Date and TimeZone classes are subsets of the J2SE
classes of the same name. An implementation is only required to
support a single time zone, which ideally is the user's local
time zone.
Apart from the classes listed above, the CLDC provides no
support for any formatting of strings, numbers, currencies or
other locale-specific operations. Profiles based on the CLDC
are allowed to add more internationalization and localization
features if appropriate or necessary for the target set of
applications. For example, the Mobile Information Device Profile
(MIDP) requires the implementation to define a
microedition.locale system property that returns the device's
locale in language-country format (as in "en-US" or "fr-FR").
Also, any HTTP requests that a MIDlet (a Java program that
follows the MIDP specifications) makes must set a
Content-Encoding header so that web servers can return correctly
encoded text content. Other profiles can include more support
for writing world-aware applications.
With only a bare minimum of support available, you can write
your own code to handle application localization, much as you
might have done if you were still programming with the original
Java 1.02 classes. Resource bundles, for example, are just a set
of classes with a particular interface that are searched in
a particular order based on the desired locale information.
Here is some code that simulates a resource bundle:
import java.util.Hashtable;
public class ResourceBundle {
private static Hashtable groups = new Hashtable();
public static Object getObject( String group, String key ) {
ResourceBundle bundle;
synchronized( groups ){
bundle = (ResourceBundle) groups.get( group );
if( bundle == null ){
bundle = loadBundle( group );
}
}
return bundle.getResource( key );
}
public static String getString( String group, String key ) {
return (String) getObject( group, key );
}
public static ResourceBundle loadBundle( String name ) {
ResourceBundle bundle = null;
Locale locale = Locale.getDefaultLocale();
String language = locale.getLanguage();
String country = locale.getCountry();
try {
bundle = (ResourceBundle)
Class.forName( name ).newInstance();
}
catch( Exception e ){
}
if( language != null ){
ResourceBundle child;
try {
child = (ResourceBundle) Class.forName(
name + '_' + language ).newInstance();
child.setParent( bundle );
bundle = child;
}
catch( Exception e ){
}
if( country != null ){
try {
child = (ResourceBundle) Class.forName(
name + '_' + language + '_' +
country ).newInstance();
child.setParent( bundle );
bundle = child;
}
catch( Exception e ){
}
}
}
if( bundle == null ){
bundle = new ResourceBundle();
}
groups.put( name, bundle );
return bundle;
}
protected Hashtable resources = new Hashtable();
private ResourceBundle parent;
protected ResourceBundle() {
}
protected void setParent( ResourceBundle parent ) {
this.parent = parent;
}
protected Object getResource( String key ) {
Object obj = null;
if( resources != null ){
obj = resources.get( key );
}
if( obj == null && parent != null ){
obj = parent.getResource( key );
}
return obj;
}
public static class Locale {
private String language = "en";
private String country = "US";
public Locale( String language, String country ) {
this.language = language;
this.country = country;
}
public Locale( String locale ) {
if( locale != null ){
int pos = locale.indexOf( '-' );
if( pos != -1 ){
language = locale.substring( 0, pos );
locale = locale.substring( pos+1 );
pos = locale.indexOf( '-' );
if( pos == -1 ){
country = locale;
} else {
country = locale.substring( 0, pos );
}
}
}
}
public String getLanguage() {
return language;
}
public String getCountry() {
return country;
}
private static Locale defaultLocale = new Locale(
System.getProperty( "microedition.locale" ) );
public static Locale getDefaultLocale() {
return defaultLocale;
}
public static void setDefaultLocale( Locale locale ) {
defaultLocale = locale;
}
}
}
Define the resources using a set of classes sharing a common base
name, as in the following:
// Default locale (base name)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -