Related
This question already has answers here:
Java : parse java source code, extract methods
(2 answers)
Closed 1 year ago.
I have tried to develop a regex that captures a method and its body (The modifier is not important), but I could not develop a solid solution. The regex that I came up with so far is this: \\b\\w*\\s*\\w*\\s*\\(.*?\\)\\s*\\{([^}]+)\\}
It does not capture the methods correctly because it does not consider matching balanced Curley braces. Thus, sometimes it captures part of the method and not all. What am I doing wrong or what could I do to improve the solution that can capture the whole method!
You can't do this. It's impossible.
The 'regular' in 'Regular Expression' refers to a certain subset of grammars; the so-called 'Regular Grammars'.
Here's the thing:
Non-Regular Grammars cannot be parsed with regular expressions.
Java (the language) is Non-Regular.
Thus, you can't use regular expressions for this, QED.
So, how do you parse java?
There are many ways; so far, java is still so-called LL(k) parseable, which means that just about every 'parser/grammar' library out there will be capable of parsing java code, and many such libraries ship with a java grammar as an example. These usually aren't quite perfect, but pretty good.
A basic web search gets you many options. Alternatively, javac is free (but GPL, you'd have to GPL anything you build with it), and ecj (the parser that powers eclipse, amongst other things) is open source with a more permissive license. It's also faster. It's also far harder to use, so there's that.
These are fairly complex tools. However, java is a very complex language (much programming languages are). Parsing them is decidedly non-trivial.
Before you think: Geez, surely it can't be this hard, consider:
public void test {
{}
String x = "{";
}
Which is legal java.
Or:
public void test() {
// method body
\u007D
That really is legal java, that \u007D thing closes it. Of course...
public void test() {
//{} \u007D
}
Here the \u thing doesn't. It is a real closing brace, but, that is in a comment.
Another one to consider:
public void test() {
class Foo {
String y = """
}
""";
}
}
Hopefully, considering the above, you realize you stand absolutely no chance whatsoever unless you use a parser that knows about the entire language spec.
Is there any tricky way to use Java reserved words as variable, method, class, interface, package, or enum constant names?
This is a valid question. Such a thing is possible in other languages. In C#, prefix the identifier with # (as asked before); in Delphi, prefix with &. But Java offers no such feature (partly because it doesn't really need to interact with identifiers defined by other languages the way the .Net world does).
No, there is no way. That's why they're labeled "reserved".
Most often this issue comes up for "class", in this case it is customary to write "clazz".
Strictly speaking you can't, unless you get your hands on a buggy compiler implementation that doesn't adhere to the Java language spec.
But where there's a will, there's a way. Copy the following code into your IDE, switch the source file encoding to UTF-16 and here we go:
public class HelloWorld {
public static void main(String[] args) {
HelloWorld.nеw();
}
public static void nеw () {
System.out.println("Hello,World");
}
}
This code is a well-formed and valid Java class. However, as you have guessed there is a little trick: the 'е' character within "new" identifier does not belong to the ASCII character set, it is actually a cyrrilic 'е' (prounanced 'YE').
Current Java language spec explicitly permits, and this an important point to make, the use of Unicode for naming identifiers. That means that one has an ability to freely call her or his classes in French, Chinise or Russian if they wish. It is also possible to mix and match the alphabets within code. And historically, some letters within Latin and other alphabets are lookalikes.
As a result: no, you can't use the reserved words as identifiers, but you can use identifiers that look exactly like reserved words.
Whether anyone should be doing it is a totally different matter.
No, you can't do this. For more information please go to JLS Sections 3.8, 3.9
The following character sequences,
formed from ASCII letters, are
reserved for use as keywords and
cannot be used as identifiers (§3.8):
Keyword: one of
abstract continue for new switch
assert default if package synchronized
boolean do goto private this
break double implements protected throw
byte else import public throws
case enum instanceof return transient
catch extends int short try
char final interface static void
class finally long strictfp volatile
const float native super while
Yes, there is.
You have to use reserved words from the future.
Like what happened with different methods called assert() in pre-1.4 code.
Hope it helps!
In Scala you can use backticks. For example: myVarialbe.`class`
Not sure what you're trying to do, but $ is a valid character in identifiers, so you could do, say:
int $return = 5;
It looks a little weird, but it does work.
I know it's old question still, might help someone.
It's possible by using GSON's Field Naming Support
eg.
#SerializedName("new")
private String New;
public String getNew ()
{
return New;
}
public void setNew (String aNew)
{
New = aNew;
}
Huh? Why would you want to do that? You can write them in l33t, that will fool the compiler.
class cl4ss {
String r3turn() {
return "but why?";
}
}
There is no way to use reserved words with the javac compiler.
Technically, you can edit the names inside the class file once it's compiled to be anything you want: at that stage, the VM doesn't care, because it's not dealing with source code any more. I believe some obfuscators use this technique.
PL/1 (a 1960's IBM mainframe programming language still around today) rather famously required that while some words act like keywords in certain contexts, all words can be used as identifiers. This isn't even that hard to do in a parser if you set out to be consistent about it. PL/1 was considered to a rather big langauge, and the langauge committee worried that many programmers wouldn't learn all of it, and then would get suprised when they tried to use the keyword from a part they didn't know as an identifier.
So you could write things like:
IF BEGIN=ELSE THEN CALL=3 ELSE CALL FOO(ENDIF) ENDIF
As others have noted here, the ability to do this isn't a recommendation.
The Java designers decided the number of keywords in the langauge was modest, and reserved the set. They even reserved 'GOTO', which isn't actually allowed in any real Java program.
If you really need to use a field/local variable/method named the same as a reserved word, I suggest appending an underscore at the end of the name:
// JPA entity mapping class:
private Boolean void_;
public Boolean getVoid_() { ... }
void setVoid_(Boolean void_) { ... }
It is a more readable choice (IMHO) than appending chars at the beginning of the name (fVoid, aVoid, vVoid, etc.)
The code above is a real world case that happened to me, working with a legacy database, in which the invoice table had a field named void indicating whether the document had been voided or not.
This question already has answers here:
Can I have macros in Java source files
(9 answers)
Closed 6 years ago.
In C i used to use #define p printf
to help me code easily rather than typing printf every time
let me give an example to understand better
p("hello world");
it does the job of
printf("hello world");
There is a way in java to do this I went through it long back Its not a duplicate question as they answered there is no way Iam sure of there is a way to do this using ENUM
How can I implement this in java
You need to use a method in a helper class.
e.g.
enum Helper {;
static void p(String fmt, String... args) { System.out.printf(fmt, args); }
static void p(Number n) { System.out.print(n); }
}
so you can call
import static mypackage.Helper.p;
p("hello world");
There is no scanf though you can use a Scanner to do something similar.
Most of the useful things you can do with macros, you can do with simple Java syntax. In term the JIT will optimise the code at runtime to get the same performance benefits.
Simple answer: you don't. Java doesn't have that kind of text substitution.
Actually, you shouldn't be making those types of substitutions in C, either. A #define like that is a recipe for trouble.
For the love of god. Don't do this. You'll have a lot of unexpected behavior in your code.
However you could learn some shortcuts like typing "syso" + Return (in Eclipse) or "sout" +Return (in Netbeans). Does not shorten your code, but it's faster.
There is no similar macro available in Java. You could write your own methods that delegate to System.out.ṕrintln and the likes, but it would probably be unnecessary work for very little gains.
Think of it this way, typing out those words will make your fingers nimbler.
Being a Java programmer, I don't really have a Groovy background, but I use Groovy a lot lately to extend Maven (using GMaven). So far, I could use all the Java code I need in Groovy with the added Groovy sugar (metaclass methods, more operators, closures). My knowledge of Groovy is far from complete, but I like it, especially for Scripting purposes (I'm a bit careful about using a non-static typed language in an enterprise scenario, but that's not the topic here).
Anyway, the question is:
Is every bit of valid Java code automatically valid Groovy code? (I am talking about Source code, not compiled classes, I know Groovy can interact with Java classes.) Or are there Java constructs that are illegal in Groovy? Perhaps a reserved Groovy keyword that could be used as an identifier in Java, or something else? Or has Groovy deliberately been designed to be 100%-source compatible with Java?
Nope. The following are keywords in groovy, but not Java:
any as def in with
Additionally, while not keywords, delegate and owner have special meaning in closures and can trip you up if you're not careful.
Additionally, there are some minor differences in the language syntax. For one thing, Java is more flexible about where array braces occur in declarations:
public static void main(String args[]) // valid java, error in groovy
Groovy is parsed differently, too. Here's an example:
public class Test {
public static void main(String[] args) {
int i = 0;
i = 5
+1;
System.out.println(i);
}
}
Java will print 6, groovy will print 5.
While groovy is mostly source compatible with java, there are lots of corner cases that aren't the same. That said, it is very compatible with the code people actually write.
It isn't.
My favorite incompatibility: literal arrays:
String[] s = new String[] {"a", "b", "c"};
In Groovy, curly braces in this context would be expected to contain a closure, not a literal array.
There's a page on the Groovy site which documents some of the differences, and another page which lists gotchas (such as the newline thing)
There are other things as well, one example being that Groovy doesn't support the do...while looping construct
Others have already given examples of Java syntax that is illegal in Groovy (e.g. literal arrays). It is also worth remembering that some syntax which is legal in both, does not mean the same thing in both languages. For example in Java:
foo == bar
tests for identity, i.e. do foo and bar both refer to the same object? In Groovy, this tests for object equality, i.e. it returns the result of foo.equals(bar)
Is there any tricky way to use Java reserved words as variable, method, class, interface, package, or enum constant names?
This is a valid question. Such a thing is possible in other languages. In C#, prefix the identifier with # (as asked before); in Delphi, prefix with &. But Java offers no such feature (partly because it doesn't really need to interact with identifiers defined by other languages the way the .Net world does).
No, there is no way. That's why they're labeled "reserved".
Most often this issue comes up for "class", in this case it is customary to write "clazz".
Strictly speaking you can't, unless you get your hands on a buggy compiler implementation that doesn't adhere to the Java language spec.
But where there's a will, there's a way. Copy the following code into your IDE, switch the source file encoding to UTF-16 and here we go:
public class HelloWorld {
public static void main(String[] args) {
HelloWorld.nеw();
}
public static void nеw () {
System.out.println("Hello,World");
}
}
This code is a well-formed and valid Java class. However, as you have guessed there is a little trick: the 'е' character within "new" identifier does not belong to the ASCII character set, it is actually a cyrrilic 'е' (prounanced 'YE').
Current Java language spec explicitly permits, and this an important point to make, the use of Unicode for naming identifiers. That means that one has an ability to freely call her or his classes in French, Chinise or Russian if they wish. It is also possible to mix and match the alphabets within code. And historically, some letters within Latin and other alphabets are lookalikes.
As a result: no, you can't use the reserved words as identifiers, but you can use identifiers that look exactly like reserved words.
Whether anyone should be doing it is a totally different matter.
No, you can't do this. For more information please go to JLS Sections 3.8, 3.9
The following character sequences,
formed from ASCII letters, are
reserved for use as keywords and
cannot be used as identifiers (§3.8):
Keyword: one of
abstract continue for new switch
assert default if package synchronized
boolean do goto private this
break double implements protected throw
byte else import public throws
case enum instanceof return transient
catch extends int short try
char final interface static void
class finally long strictfp volatile
const float native super while
Yes, there is.
You have to use reserved words from the future.
Like what happened with different methods called assert() in pre-1.4 code.
Hope it helps!
In Scala you can use backticks. For example: myVarialbe.`class`
Not sure what you're trying to do, but $ is a valid character in identifiers, so you could do, say:
int $return = 5;
It looks a little weird, but it does work.
I know it's old question still, might help someone.
It's possible by using GSON's Field Naming Support
eg.
#SerializedName("new")
private String New;
public String getNew ()
{
return New;
}
public void setNew (String aNew)
{
New = aNew;
}
Huh? Why would you want to do that? You can write them in l33t, that will fool the compiler.
class cl4ss {
String r3turn() {
return "but why?";
}
}
There is no way to use reserved words with the javac compiler.
Technically, you can edit the names inside the class file once it's compiled to be anything you want: at that stage, the VM doesn't care, because it's not dealing with source code any more. I believe some obfuscators use this technique.
PL/1 (a 1960's IBM mainframe programming language still around today) rather famously required that while some words act like keywords in certain contexts, all words can be used as identifiers. This isn't even that hard to do in a parser if you set out to be consistent about it. PL/1 was considered to a rather big langauge, and the langauge committee worried that many programmers wouldn't learn all of it, and then would get suprised when they tried to use the keyword from a part they didn't know as an identifier.
So you could write things like:
IF BEGIN=ELSE THEN CALL=3 ELSE CALL FOO(ENDIF) ENDIF
As others have noted here, the ability to do this isn't a recommendation.
The Java designers decided the number of keywords in the langauge was modest, and reserved the set. They even reserved 'GOTO', which isn't actually allowed in any real Java program.
If you really need to use a field/local variable/method named the same as a reserved word, I suggest appending an underscore at the end of the name:
// JPA entity mapping class:
private Boolean void_;
public Boolean getVoid_() { ... }
void setVoid_(Boolean void_) { ... }
It is a more readable choice (IMHO) than appending chars at the beginning of the name (fVoid, aVoid, vVoid, etc.)
The code above is a real world case that happened to me, working with a legacy database, in which the invoice table had a field named void indicating whether the document had been voided or not.