How to check if a string is a valid class identifier?

Is there a good way to verify that a string represents a valid (fully qualified) Java class name? For example, org.comPAny.ClassName or even mYcRAZYcLASSnAME are valid class names, but something like org..package.MyClass or org.ClassName. are not. I want to check if the class name is correct without loading this class.

Is there any convenient method in Java to test this? Or can you provide a regex that is provided for all cases?

EDIT: Please do not offer third-party libraries.

+7
source share
7 answers

If you really need a bulletproof solution, split the line into "\\." and use first

 Character.isJavaIdentifierStart 

and in the cycle

 Character.isJavaIdentifierPart 

to verify that the parts are valid identifier names.

Edit: #split(String) interprets the string as a regular expression, so make sure you split the string into "\\." , not just "." as you expect by the principle of least surprise. What a bad API design, yikes! This is what you get from the fact that you don't have regular expressions in your language ...

+9
source

Different versions of the Java platform support different versions of Unicode.

Thus, different versions will support different valid identifiers.

The following accounts are for identifiers outside of BMP and reserved Java words.

 import java.util.Arrays; public enum PackageName { SIMPLE, QUALIFIED, INVALID; public static final PackageName check(String name) { PackageName ret = PackageName.INVALID; int[] codePoint; int index = 0, dotex = -1; boolean needStart = true; escape: { if(name == null || name.isEmpty()) break escape; if(name.codePointAt(0) == '.') break escape; codePoint = name.codePoints().toArray(); while (index <= codePoint.length) { if(index == codePoint.length) { if(codePoint[index - 1] == '.'){ ret = PackageName.INVALID; break escape;} int start = dotex + 1; int end = index; start = name.offsetByCodePoints(0, start); end = name.offsetByCodePoints(0, end); String test = name.substring(start, end); if(!(Arrays.binarySearch(reserved, test) < 0)){ ret = PackageName.INVALID; break escape;} if(!(ret == PackageName.QUALIFIED)) ret = PackageName.SIMPLE; break escape; } if(codePoint[index] == '.') { if(codePoint[index - 1] == '.'){ ret = PackageName.INVALID; break escape;} else { needStart = true; int start = dotex + 1; int end = index; start = name.offsetByCodePoints(0, start); end = name.offsetByCodePoints(0, end); String test = name.substring(start, end); if(!(Arrays.binarySearch(reserved, test) < 0)) break escape; dotex = index; ret = PackageName.QUALIFIED; } } else if(Character.isJavaIdentifierStart(codePoint[index])) { if(needStart) needStart = false; } else if((!Character.isJavaIdentifierPart(codePoint[index]))){ ret = PackageName.INVALID; break escape; } index++; } } return ret; } private static final String[] reserved; static { reserved = new String[] { "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "false", "final", "finally", "float", "for", "if", "goto", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while" }; } } 
+3
source
 public static boolean isValidJavaIdentifier(String s) { // an empty or null string cannot be a valid identifier if (s == null || s.length() == 0) { return false; } char[] c = s.toCharArray(); if (!Character.isJavaIdentifierStart(c[0])) { return false; } for (int i = 1; i < c.length; i++) { if (!Character.isJavaIdentifierPart(c[i])) { return false; } } return true; } 

Link: http://www.java2s.com/Code/Java/Reflection/CheckwhetherthegivenStringisavalididentifieraccordingtotheJavaLanguagespecifications.htm

+2
source

There is a good solution for your problem:

 public static boolean isFullyQualifiedClassname( String classname ) { if (classname == null) return false; String[] parts = classname.split("[\\.]"); if (parts.length == 0) return false; for (String part : parts) { CharacterIterator iter = new StringCharacterIterator(part); // Check first character (there should at least be one character for each part) ... char c = iter.first(); if (c == CharacterIterator.DONE) return false; if (!Character.isJavaIdentifierStart(c) && !Character.isIdentifierIgnorable(c)) return false; c = iter.next(); // Check the remaining characters, if there are any ... while (c != CharacterIterator.DONE) { if (!Character.isJavaIdentifierPart(c) && !Character.isIdentifierIgnorable(c)) return false; c = iter.next(); } } return true; } 

Source: http://www.java2s.com/Code/Java/Reflection/DeterminewhetherthesuppliedstringrepresentsawellformedfullyqualifiedJavaclassname.htm

+2
source

The correct way to do this is to use the javax.lang.model.SourceVersion.isName method (part of the standard Java library).

+2
source

Did you see that?

http://commons.apache.org/sandbox/classscan/apidocs/org/apache/commons/classscan/builtin/ClassNameHelper.html

Here's the isValidIdentifier method * Check if the supplied name is a valid part of the java package name or class identifier.

+1
source

Bulletproof solution made easy with regular expressions:

 String NAME = "\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*"; String DOT = "\\."; String DOTTED_NAME = NAME + "(?:" + DOT + NAME + ")*"; Pattern DOTTED_NAME_PATTERN = Pattern.compile(DOTTED_NAME); boolean isJavaName(String name) { Matcher matcher = DOTTED_NAME_PATTERN.matcher(name); return matcher.matches(); } 
0
source

All Articles