0

I was doing a Junit tutorial and I came across this normalize function that was being tested. It was defined like this:

 public static String normalizeWord(String word) {
        try {
            int i;
            Class<?> normalizerClass = Class.forName("java.text.Normalizer");
            Class<?> normalizerFormClass = null;
            Class<?>[] nestedClasses = normalizerClass.getDeclaredClasses();
            for (i = 0; i < nestedClasses.length; i++) {
                Class<?> nestedClass = nestedClasses[i];
                if (nestedClass.getName().equals("java.text.Normalizer$Form")) {
                    normalizerFormClass = nestedClass;
                }
            }
            assert normalizerFormClass.isEnum();
            Method methodNormalize = normalizerClass.getDeclaredMethod(
                                                            "normalize",
                                                            CharSequence.class,
                                                            normalizerFormClass);
            Object nfcNormalization = null;
            Object[] constants = normalizerFormClass.getEnumConstants();
            for (i = 0; i < constants.length; i++) {
                Object constant = constants[i];
                if (constant.toString().equals("NFC")) {
                    nfcNormalization = constant;
                }
            }
            return (String) methodNormalize.invoke(null, word, nfcNormalization);
        } catch (Exception ex) {
            return null;
        }
    }

How does this function work? What is it actually doing?

Egg
  • 246
  • 1
  • 5
  • 16

3 Answers3

5

It does the same as:

import java.text.Normalizer;

try {
    return Normalizer.normalize(word, Normalizer.Form.NFC);
} catch (Exception ex) {
    return null;
}

Except that all operations are performed via Reflection.

Pavel Minaev
  • 99,783
  • 25
  • 219
  • 289
  • And it should be written that way unless you really need to compile (as opposed to just run) on pre-Java6. If you catch all Exceptions (and maybe some class-loading related Errors), too, then this code will even degrade gracefully on JDK5 where the Normalizer class is not present. You will need to compile on Java6, though. (With the reflective version, you could compile on older Java as well, although it could be argued that you are not actually compiling anything, what with all the reflection in there). – Thilo Aug 15 '09 at 00:20
3

It's using reflection to call

java.text.Normalizer.normalize(word, java.text.Normalizer.Form.NFC);

Presumably to allow it to run on Java versions before 1.6 which don't have this class.

Ben Lings
  • 28,823
  • 13
  • 72
  • 81
2

This function offers services regarding strings normalization for Unicode. In Unicode, you can represent the same thing in many ways. For example, you have a character with accent. You can represent it joined, using one single Unicode character, or decomposed (the original letter, without accents, then the modifier - the accent).

The class comes in Java 6. For Java 5, there's a SUN proprietary class.

See class info.olteanu.utils.TextNormalizer in Phramer project (http://sourceforge.net/projects/phramer/ , www.phramer.org ) for a way to get a normalizer both in Java 5 (SUN JDK) and in Java 6, without any compilation issues (the code will compile in any version >= 5 and the code will run in both JVMs, although SUN discarded the Java 5 proprietary class).

Thilo
  • 257,207
  • 101
  • 511
  • 656
Marian
  • 2,617
  • 1
  • 16
  • 13