What's the point of String[] args in Java? - java

Whenever you declare the main method in a class, you always have to do a String array called "args". What's the point? Unless I live under a rock, command line agruments in Java are barely used anymore. And when I try and run this...
//this program won't compile
public class SomeClass {
public static void main(){
System.out.println("This text will never be displayed :(");
}
}
The output shows this in red text:
Error: Main method not found in class SomeClass, please define the main method as:
public static void main(String[] args)
I, the newbie Java programmer, would greatly appreciate it if anyone told my why it's required to enter that parameter into a main method.

Because that is the signature of the main method that is called when you execute a Java class. There needs to be some convention which method will be executed. By convention it is the
public static void main(String[] args) method
And yes, you do live under the rock, there are plenty of situations when command line arguments are used. Why would they not be used?
You could ask: why require it? Why not just pick any other main method? The answer is that it would be adding complexity with 0 benefit. As is now, main function looks distinctive. If you look at it, you know it is the one that will get called. If any main would be called, you would have to always ask yourself: is the main I am looking at the one to be invoked, or is there another main in this class which takes precedence?

Short answer: because that's the way Java is.
Command-line arguments are used all the time, but you don't always see them due to launcher scripts, or because the program's running on a server, etc.
That said, a lot of time the command line arguments are of the -D variety, slurped up by the JVM before reaching main. But it depends on what you're doing.

A Java application can accept any number of arguments from the command line. This allows the user to specify configuration information when the application is launched. (From Command-Line Arguments) and as everyone else said here, it is the way it is!
For gods sake,Please Don't say if I don't need this ,no-one else need this! :)

Because
Command-line arguments are still used, even by many UI programs (did you know that Microsoft Outlook supports some very handy command-line arguments?)*; and:
That's Just How Java Works (TM). Among other things, it reduces the complexity of both the code (by disallowing multiple forms and possible accidental shadowing) and run-time (by not needing to find out "which main" to call). Allowing a secondary form without "args" just adds too little.
Happy coding...
*Yes, Outlook is not Java. However, if Outlook has command-line arguments, well, they must still be worth something -- it was a hyperbole ;-)
Almost every UI program that deals opening reading files will allow specifying which file to open via command-line arguments (Gimp, Notepad, Firefox, to name a few others). Among other things, this is to allow integration with "double clicking to open" on items in Windows Explorer and similar.

I actually have no idea why it's required, other than to say that it is a syntactical convention. In the same way that a function is (defined function-name()) in Lisp/Scheme, or there are do..end blocks in Ruby, the syntax of a Java Main function is with String[] args.
As for not using command line arguments, it's entirely dependent on the program. Entirely. I write programs in java all the time that take command line arguments; it's just a question of what you're trying to accomplish.

One case I can think of is, when you want to have a command line driven interface for your software along with the GUI. An example is the Android tools, all of them have console driven interfaces.

Command-line argument support is largely standard among programming languages. Even in this age of GUIs, there are all sorts of hidden ways to run a program with command line arguments. I know Windows has shortcut configurations for advanced users where you can run a program with a given set of command line arguments, for example.
Java also enforces types, and by extension function signatures (look it up on Google if you don't know what those are). The main function is expected to take an array of Strings - if the main function you define doesn't match that argument signature (1 argument, array of Strings), then it causes an incompatibility.
Java supports function overloading (you can define the same function name several times with different arguments). To find which function to invoke, Java takes the input argument types and looks for an applicable defined function that takes the matching arguments.
When the program runs, Java specifically looks for a function named main with 1 argument (String []). Your program doesn't define a main function with that argument specification, so this lookup fails with an error message.

Related

permanent storage of parameter names in bytecode using javac -parameters <Classname>

What I'm doing
I'm using reflection in my code to decouple all my classes and To do so I need to be able to dynamically create instances of objects. I've done this by text matching parameter names to input data. To do a text match however, I need access to the formal parameter names rather than the synthetic arg0, arg1 ... that I know gets created if IsNamePresent returns false.
What I've done
I researched how to get the formal names (google searching things like: "when I compile my java classes with the parameter option enabled, does that make reflection work forever? or only one time when the classes are run?" to no useful results). I've also tried searches similar to that here and seen info related to javac with one of the questions being "Drawbacks of javac -parameters flag" as an example. While these addressed parts of my question they really didn't answer the meat of what I need. I've found that in java 8 you can just do "javac -parameters " and you will be fine. Note that I had to use the directory of the jdk as the starting point (my command line input looks exactly like this):
C:\Program Files\Java\jdk-10.0.1\bin>javac -parameters C:\Users\abbotts1\IdeaProjects\project\src\Sales_Rep_Data\*.java
and so far that works without any errors and my project has bytecode compiled files in it now so I know its doing something. Just what exactly (or if its as a result of the above) is a mystery to me because there is no timestamp or anything I can find for these files that points to which command I tried that made it (I've been trying these commands for a while).
Detailed description of question scope
My question is this: is this command line input the only way to get formal parameters. If it is then, am I doing it right (correct input syntax)? If I'm doing it right then how can I make it so that when I debug my code and run param.getName() it actually returns the formal name? So far I've ran the above command on the command line and tried to debug in my java code this line:
Boolean check = param.isNamePresent();
where param is just the parameter coming from a for-each loop that uses the constructor of the class I am getting through reflection. Point is, every-time I run it this Boolean returns false in the debugger and the names are synthetic (arg0, arg1 ect). I want it to return true (and actually use the formal names) so I can debug the rest of my code.
If this isn't the only way to achieve the stated goal of getting formal parameter names then where can I find a better way? I've seen some framework stuff and heard of Eclipse being used to do this, however I don't want to get too deep into new software just to accomplish one thing AND I am working so I don't have administrator privileges (which is why I needed to specify the jdk in cmd directly rather than just set the PATH variables the usual way). This would make it a hassle to have to download something like Eclipse.
Update
I've researched into using annotations to get the parameter names since I have no good idea why the compiled class won't actually store the parameter names. This strategy was suggested in an initial answer (since deleted) and I took it upon myself to go learn some basic annotations. They have worked to a point but right now I'm getting a wrong arguments error where I shouldn't. I've checked the debugger and the number of arguments passed in are the same number needed so it must be a type error with the wrapping/unwrapping according to the javadoc for the newInstance(Object[]) method). I want to be able to initialize null parameters and I think thats the source of my problem (i. e. null type errors or something but not shown as NPE). Other potential sources include the fact that I'm passing in an Object[] and typing it stricter in the class (i.e. newInstance(Object[] array) is creating an instance of a class that has String parameters and other various sub classes of Object including array lists) Since asking about that error here would constitute an XY problem I won't ask but just describe it for clarification on the original question. My original question still stands even as this workaround is being worked on because I'd still love to know why compiling this class with the -parameters flag didn't store the parameter names. I'm 99% sure the class path is correct since I copy pasted it from the directory. This sounds silly but do I have to actually run the class using the below line?
C:\Program Files\Java\jdk-10.0.1\bin>java C:\Users\abbotts1\IdeaProjects\project\src\Sales_Rep_Data\Data_Parser.java
I was under the impression that compiling it with the parameters flag was all you needed and then the formal parameter names would be available.

Java startup arguments

I searched dozens of threads about this topic.
What I am looking for is to start a program using custom attributes, like:
java -C:/randof/...FROMPATH -C:/rudolf/...TOPATH
I want to start the program using the commandline (obviously) and directly passing arguments in it. The from and topath that are passed should be able to be used internally.
I cannot properly extract them though. If I iterate over "args", it brings me an error "Unrecognized option:". How is the thing I wanna achieve possible?
And is it only possible by passing "VM-Arguments"? This would mean that the arguments would be available over all java programs that run at the same time if not mistaken. I would like to enclose the scope if possible.
use -- before the arguments of your program:
java -C... -other-java-options -- -your-app-options etc
in the above command line java is the executable and all the rest are arguments that are passed by your shell to java. Java tries to interpret them. The common way to tell a program, that the arguments to it are ending here, and from here the arguments are meant for something else (in this case to your java code) so don't bother parsing them, just pass them on.
The primary way to get command line options to be recognized as options to the program you are writing and not as options to the java executable is to use defines -Dproperty=value and then you can pull these out using the System object. If you don't insist on having a leading dash, then the options will become elements in the String[] parameter passed to main.
Other -XXXX arguments are passed to the java executable (actually the -D is passed to the java executable too, but the java executable then makes it available to the program.
I think you shouldn't use "-" when you give the arguments.
Just write (if the compiled file has the name SofExample.class):
java SofExample C:/fromPath C:/toPath
and then in the program you will be able to use the arguments, because they will be in the args String array.
For example:
public class SofExample {
public static void main(String[] args) {
final String fromPath=args[0];
final String toPath=args[1];
//Args checks and other codes come here to use fromPath and toPath...
}
}
These arguments can be used only in this program code, not in all programs running in the JVM.
I hope I could help. Regards.
None of the answers did what I wanted (maybe my question was badly formulated), but I found the solution.
You can just add the parameters you need without a specific operator.
Consider the following main method:
public static void main(String...args) {
for (String a : args) {
System.out.println(a);
}
}
Here is the output for the following inputs:
java -jar YOURJARFILENAME.jar C:/Users/RUDOLF
//Output:
C:/Users/RUDOLF
java -jar YOURJARFILENAME.jar C:/abc C:/def
//Output:
C:/abc
C:/def
If you need to hand over filepaths that contain whitespaces, just add "" around every path. This will ensure that it is read as one argument and not be splitted up.
Problem: java -jar YOURJARFILENAME.jar C:/users/arnold schwarzenegger/desktop
//Output:
C:/users/arnold
chwarzenegger/desktop
Solution: java -jar YOURJARFILENAME.jar "C:/users/arnold schwarzenegger/desktop"
//Output:
C:/users/arnold schwarzenegger/desktop

So, how exactly does the Java main method work?

public static void main(String [] args)
This thing has been quite the enigma ever since I started programming. I understand it passes an array of Strings to the command line, but where exactly does it do that and how does it interpret it?
I'm pretty sure I'm wrong here, but my current understanding is that whatever you write in the main method is then translated into machine and passed into the computer as a string. Well, that's all fine and dandy, but then how does it understand numeric values if everything is a String?
Also, it's a bit weird when it comes to methods. Usually, when designing a method, you would write the formal parameters that you'd pass to it, and what you want to do with those parameters. But with the main method, you are defining the parameters while you're writing the code inside the main method! how does that even work?
The public static void main(String[] args) method in Java is the method that gets called when the user starts running your program. Inside this method, it is up to you to write whatever code (classes and methods) you need to make the program work.
Yes, parameters for this method are strings, but this is because when the program is executed from the command line, these args are the parameters that the user typed after the name of the class to execute. It is up to your code to parse them into numbers if that is what you require.
I'm pretty sure I'm wrong here, but my current understanding is that
whatever you write in the main method is then translated into machine
and passed into the computer as a string. Well, that's all fine and
dandy, but then how does it understand numeric values if everything is
a String?
This statement doesn't make particular sense. Yes, the class, which may contain the main method, is compiled to byte code, which can be read/interpreted by the JVM and executed on the machine.
When the JVM is executed (by running the java command) it looks for the main method in the specified class (or if you are executing a jar file, the class specified by the Main-Class manifest entry). If found, it will pass the command line parameters as a String array to your main method.
Also, it's a bit weird when it comes to methods. Usually, when
designing a method, you would write the formal parameters that you'd
pass to it, and what you want to do with those parameters. But with
the main method, you are defining the parameters while you're writing
the code inside the main method! how does that even work?
Because it's impossible for the JVM to know what parameters might be sent to it from the command line, it wraps all the parameters up within a String array, meaning that, you could have lots and lots of different parameters sent to your main method.
It is up to you to interpret these parameters based on the needs of your program and determine if they suitable enough for you to continue execution.
Take a look at:
Chapter 12 of the Java Language Specification: Execution
Lesson: A Closer Look at the "Hello World!" Application
for more details.
Historically, the main method comes from C/C++ as they also have a concept of a main function which operates in a similar fashion
I am not familiar with the internals of the JVM, but assuming it is running on a typical Linux/Unix systems, here are some possibilities:
1) The JVM itself is the actual program that is invoked giving it the the .class name as the input (containing the main method) along with additional args if needed - e.g.:
java SomeProgram input1 input2 .....
where SomeProgram.class is the compiled from SomeProgram.java which is the class that has the usual main() method.
2) Now the JVM in a typical Linux/Unix environment is a 'ELF binary' (executable and linking format) which has the 'main' method defined. All the gory details are described here including how the inputs are passed from a shell to a running executable (on a Intel platform):
http://linuxgazette.net/84/hawk.html
3) In short the JVM gets the inputs as described in (2), and then effectively runs the Someclass.main() method by copying all the inputs to the String[] array.
4) All inputs are treated as String, so if you need to treat some inputs as numeric, you would need to explicitly cast them as needed.
Although the ELF standard is part of Linux/Unix systems, I am assuming something similar is happening in other platforms supporting Java.
I am hoping someone with more understanding of JVM internals can correct me if I am wrong.

Can I invoke a java method other than main(String[]) from the command line?

Can I invoke a java method other than main(String[]) from the command line?
If you don't have a main function, you can just add one, and if you do, you can just add a series of if-then blocks to the top.
public static void main(String[] args){
if (args[0].equals("MY_METHOD"))
callMyMethod();
else if(args[0].equals("MY_OTHER_METHOD"))
callMyOtherMethod();
//... Repeat ad nauseum...
else {
//Do other main stuff, or print error message
}
}
Then, from the command line:
$ java [MyPackage.]MyClass MY_METHOD
Will run your method.
This is pretty hackish - I'm almost sure it's not what you want to do, but hey, it answers the question, right?
If you install a REPL for a JVM language (Groovy probably takes the least work to get started with), then you can invoke Java methods at the REPL prompt (Groovy's is called groovysh). groovysh has some odd features (my least favorite bit is that declaring variables with def doesn't do what you'd think it should) but it's still really useful. It's an interesting feature that Groovy doesn't respect privacy, so you can call private methods and check the contents of private variables.
Groovy installs include groovysh. Download the zip file, extract it somewhere, add the location of the bin directory to the path and you're good to go. You can drop jars into the lib folder, for the code you're running and libraries used by that code, and Groovy will find them there.
Here is a bash function that lets you do just that:
function javae {
TDIR=`mktemp -d`
echo "public class Exec { public static void main(String[] args) throws Exception { " $1 "; } }" > $TDIR/Exec.java && javac $TDIR/Exec.java && java -cp $CLASSPATH:$TDIR Exec;
rm -r $TDIR;
}
Put that in ~/.bashrc and you can do this:
javae 'System.out.println(5)'
Or this:
javae 'class z { public void run() { System.out.println("hi"); } }; (new z()).run()'
It's a hack of course, but it works.
You cannot invoke even the main method from the command. The JVM invokes the main method. Its just a convention. It always needs to be "public static void main".
What is your use case?
From The Java Virtual Machine Specification
The Java virtual machine starts up by creating an initial class, which
is specified in an implementation-dependent manner, using the
bootstrap class loader (ยง5.3.1). The Java virtual machine then links
the initial class, initializes it, and invokes its public class method
void main(String[]). The invocation of this method drives all further
execution. Execution of the Java virtual machine instructions
constituting the main method may cause linking (and consequently
creation) of additional classes and interfaces, as well as invocation
of additional methods.
So main appears to be special.
No you cant
As per Java command line FAQ (which is dead now.)
You can check Java Threads FAQ
The entry point method main() is used to the provide a standard convention for starting Java programs. The choice of the method name is somewhat arbitrary, but is partly designed to avoid clashes with the Thread start() and Runnable run() methods, for example.
Check the FAQ. You will get some good knowledge about JAVA command line
No, I don't think so. main() is the entry point. That's defined by the language. You can wrap a script around the main() call ("java MyApp arg1...argn"), of course, to obscure the name (and even hide that you're using Java) and to provide your own parameter syntax and parsing -- that is a capability provided by the OS, of course, through some sort of command-line scripting language.
If you use Java to create other types of executables, like Applets or GWT applications, then the entry point is different, but I think you're thinking specifically about executables run from the command line.
No, that is not possible.
Please see the Java language specification
http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html
Ofcourse applets and servlets and other technologies may have different starting points.

Why does Java main() method accept an array of String args?

Since its possibly one of the most widely used methods of the Java language, why does it have to accept an array of Strings and doesn't work without it? For example, I could always live with:
public static void main() {}
over
public static void main(String[] args) {}
Is there a higher purpose to this than just being able to accept command-line arguments, especially since a vast majority of Java programs are GUI driven and don't need to receive args through command line?
I agree that it could be more flexible. In C# for instance, all of these are acceptable entry points:
static void Main()
static void Main(string[] args)
static int Main()
static int Main(string[] args)
The versions returning int use the return value as the exit code for the process. If you don't care about receiving any arguments, you can use one of the versions which doesn't take any. Any arguments given when the program is launched are ignored.
So yes, it could be more flexible - but it's never struck me as a significant problem in Java.
even a gui driven java app will start with some main method.
The "higher purpose" has never been to accept command line arguments.
The purpose is just to accept arguments. Period. Whenever you start any program not just Java you will always need some syntax to pass arguments
Programs always take commandline arguments. It's up to the programmer to decide if they are used for anything.
So implementing a main without a string-array would lead to more complex startup-logic and potentially confusing and errorneous behavior, for the more than debatable gain of not writing a single parameter declaration less (in your whole program!)
And given the overall verbosity of Java & the support for common templates for boilerplate code in IDEs like Eclipse, I fail to see where that's really an issue.
"Is there a higher purpose to this (..)"
Yes: legacy.
What "vast-majority" of programs do does not really make much difference in terms of what is needed to be done. There are still lots of command line programs that are driven by command line args.
Lots of GUI programs provide facilities to accept command-line switches to control their behaviour at start up.
I guess it's because many Java programs will take at least some parameters. Like C (a syntactical inspiration of Java if nothing else), Java considers the best way to provide these as parameters to main.
Even a GUI program will often take command line parameters. Just because the shell it's launched from typically doesn't ask for these parameters (by default), doesn't mean they're not supported.
there are also many java programs that receive args through command line. Think of javac, ant, maven, etc
A Java application can accept any number of arguments from the command line. This allows the user to specify configuration information when the application is launched. For example, we can pass username, password from the command line itself.
class Test {
static void connectDB(String username, String password) {
System.out.print(String.format("Username: %s, Password: %s", username, password));
// code to connect DB
}
public static void main(String args[]) {
connectDB(args[0], args[1]);
}
}
Now compile the program using javac Test.java
and Execute using java Test rootuser Test1234
The output will be:
Username: rootuser, Password: Test1234
So, we can use commandline-argument this kind of purposes.

Categories