I have code where a variable name is identical to the class name. I.e.:
class Foo {
static public void main(String[] args) {
Integer Foo;
Foo.main(args);
}
}
How can I call the main-method without renaming the variable or the class?
If it's not in the default package you could refer to it via the package name also, e.g.:
packagename.Foo.main(args);
or you can simply refer to main without the class name, e.g.:
main(args);
If class Foo is in a package, you could use the fully qualified name:
my.package.Foo.main(args);
You could also rename variable Foo; it's bad Java style to capitalize variable names. Finally, why would you want to call main from main like that? It's going to overflow the stack very quickly.
Since Integer does not have a main(...) method, this is not a problem.
More generally speaking, if you need to disambiguate, use the full package name.
use the full package name, it works.
package my.pck;
class Foo {
static public void main(String[] args) {
Integer Foo;
my.pck.Foo.main(new String[] { "arg" });
}
}
But why would you want to call main from main like that? its creating infinite loop.
I have code where a variable name is identical to the class name
Why? The simple answer is "don't". The convention is that class names start with a capital and member variable names don't, which takes care of it completely.
Related
When I use data class or the regular class and set the argument to its constructor it generates getter/setter in the Java code but in Kotlin we can achieve it by the variable name. Is it private in Java only or Kotlin replaces its getter/setter by the variable name?
The class
class Person(var name: String)
When calling it from kotlin code as you can see I call name variable
fun main() {
print(Person("Mohammed").name)
}
When calling it from Java as you can see I call the method, not the variable
public static void main(String[] args) {
System.out.println(new Person("Mohammed").getName());
}
but I can not use
public static void main(String[] args) {
System.out.println(new Person("Mohammed").name);
}
IntelliJ shows that name is private.
So, the question is - Is the argument private at all or only for the Java code?
Does Kotlin replace its getter/setter by the variable name then reverse it at runtime?
Let's start with that misconception in the question:
The question is is the argument is private at all or only for the Java code?
There is no such thing as "private for java only".
Reminder: no matter if you write Kotlin and use kotlinc, or Java with javac, in the end, your source code gets compiled into a JVM class file. And the content and information within that file determines what "users" can do with your class.
And when I compile your Person.kt class, and run javap, that is what shows up:
> javap Person.class
Compiled from "Person.kt"
public final class Person {
public final java.lang.String getName();
public final void setName(java.lang.String);
public Person(java.lang.String);
}
The point is: as you can see, there is a getter for that field.
Beyond that, there is also meta information within the class file that tells a Kotlin compiler that this class "is" a Kotlin class.
Thus the Kotlin compiler allows you to use somePerson.name "directly".
I want to create an abstract class with a main method, to prevent developers who extend it from having to implement the main method. I also want to control what happens in the main method.
The abstract base class that I'm writing extends NanoHTTPD, and you start the server by calling ServerRunner.run() with the parameter being a class object of the type of the class that you want to run.
Here is what I have so far:
public abstract class FlexibleServer extends NanoHTTPD
{
public DeadSimpleMicroserver(int port)
{
super(port);
}
public static void main(String[] args)
{
ServerRunner.run(FlexibleServer.class);
}
}
The problem is that since this class is abstract, future developers will be extending the class, so I need the parameter to ServerRunner.run() to be the ACTUAL type of the subclass, so I can't use FlexibleServer.class.
I tried changing the parameter to this.class, but then I get the compile error that "this" cannot be referenced from a static context (because main() is static).
How can get a class object of the actual subclass from main()?
If the class that you're going to pass at runtime is dynamic, then you cannot call it with a hard-coded class name. You will have to change your call to run so that you pass it either an instance of the actual class, or you would have to dynamically load the class given, for example, main method arguments.
With the above change, your problem gets resolved.
For example, if you're loading the class dynamically:
ServerRunner.run(Class.forName(args[0]));
Assuming the app will be called with the actual class name.
Alternatives include redesigning your code such that either a class name, an instance, or class object is passed in by the caller
A framework I once worked on had a base class like this, and we added a method like this:
public abstract class FrameworkServer {
// framework stuff
protected static void main(String[] args, FrameworkServer instance) {
// parse args
// actually start the instance running
}
}
And a specific server instance would need to add its own main method like so:
final class MyServer extends FrameworkServer {
public static void main(String[] args) {
main(args, new MyServer());
}
}
There is a small bit of boilerplate here for each server, but that allows you do avoid reflection and to make the code much clearer. As a bonus, the concrete subclasses can now add their own arguments to their server's constructor, which is often very useful for unit-testing.
When I create a new main.java file in the default package in my Eclipse project, it generates a main method that looks like:
public static void main(String[] args)
{
}
This immediately raises a warning that says This method has a constructor name. The suggested fix is to remove the void:
public static main(String[] args)
{
}
Now rather than a warning, I get an error: Illegal modifier for the constructor in type main; only public, protected & private are permitted. If I remove the static, my code now looks like:
public main(String[] args)
{
}
This time, I still get an error, but a different one that says:
Error: Main method not found in class main, please define the main method as:
public static void main(String[] args)
Argggh! But that takes me right back to where I started. How do I define the main method so that I don't get any errors or warnings?
I'm using Eclipse Juno Service Release 2 and JavaSE-1.7. Please note, I'm very new to Java; I come from a C# background. Also, this is probably a duplicate question, but I can't find it.
Don't call your class main, but Main.
In general, stick to the Java coding standards: start class names with a capital (Main instead of main) and you won't run into these problems.
If you name the file main.java the class has to be named main too, which is against standard (classes start with a capital letter) but possible. In a class a method named the same as the class is considered a constructor. So to fix your problem and fit the standard rename your class and the file to Main with a capital "M"
Change the name of your class from main to Main or to something else. Also, following the JavaBean API specification, your classes must be in CamelCase with the first letter in capital.
Not 100% related with question, but you should also do not create classes with the names of Java JDK classes, for example String:
public class String {
public static void main(String[] args) {
System.out.println("Try to execute this program!");
}
}
This won't only give problems to compiler/JVM but also for future readers (remember that you are a future reader of your own code as well).
Note: to fix the code above, just refer to java.lang.String class using its full name:
public class String {
public static void main(java.lang.String[] args) {
System.out.println("Try to execute this program!");
}
}
Or even better, change the name of the class.
In java, the class name and file name must match. If you have a file named main.java, then the class name has to be Main too, and in that case, the constructor method would be named main, so you couldn't have a main method.
Change your file and class name to something other than main.
class Main {
public static void main(String[] args) {
....
}
}
Starting the program through the shell: java Main works as expected but starting the program through ant:
<target name="run" depends="cmp">
<java classname="Main" classpath="."/>
</target>`
causes this error:
java.lang.IllegalAccessException: Class org.apache.tools.ant.taskdefs.ExecuteJava can not access a member of class Main with modifiers "public static"
JLS Section 12.3.3 Resolution of Symbolic References:
IllegalAccessError: A symbolic reference has been encountered that
specifies a use or assignment of a field, or invocation of a
method, or creation of an instance of a class, to which the code
containing the reference does not have access because the field or
method was declared private, protected, or default access (not
public), or because the class was not declared public.
So org.apache.tools.ant.taskdefs.ExecuteJava can't execute the method because it's enclosing class is private, but if I start the jvm pointed at a .class with a private method, it doesn't go through the same security mechanism?
This question is similar but I still don't understand
The answer is all in the question you linked to. When you run it through the JVM it has access to absolutely everything regardless of access level. When you run it through ant, which itself is another java program, it has to obey by the same rules as any other program - which means that it cannot see your main method.
If you declare your class as public class Main the problem should go away.
As to why the jvm has made this decision to allow access to private classes when starting is another matter indeed. As per the specification
12.1.4 Invoke Test.main
Finally, after completion of the initialization for class Test (during
which other consequential loading, linking, and initializing may have
occurred), the method main of Test is invoked. The method main must be
declared public, static, and void. It must accept a single argument
that is an array of strings. This method can be declared as either
public static void main(String[] args) or public static void
main(String... args)
This specifically states that the method must be public but says nothing about the class in questions, which why it works when you invoke main through the VM directly.
Try to add public modifier to the class like this:
public class Main {
public static void main(String[] args) {
....
}
}
Use public access-modifier.
Eg:
public class Main {
public static void main(String[] args) {
// Your code..
}
}
I run checkstyle on my Java code and get this error:
variable access definition in wrong order
Can somebody tell me what that means?
Could it be that you have declaration order configured in CheckStyle? Take a look at
http://checkstyle.sourceforge.net/config_coding.html#DeclarationOrder
In that link, you will notice that it says ...
*According to Code Conventions for the Java Programming Language , the parts of a class or interface declaration should appear in the following order:
Class (static) variables.
First the public class variables,
then the protected,
then package level (no access modifier), and
then the private.
Instance variables.
First the public class variables,
then the protected,
then package level (no access modifier), and
then the private Constructors Methods*
Maybe it is a little late for answering this question but in my case i had some thing like that:
public final class ClassA{
private ClassA() {
}
private static Logger LOG = LoggerFactory.getLogger(ClassA.class);
}
and after i changed the order to:
public final class ClassA{
private static Logger LOG = LoggerFactory.getLogger(ClassA.class);
private ClassA() {
}
}
my problem solved.
I'm guessing you have something like static public int. Normally, that would be written as public static int.