String class make confusion - java

Recently I just got an error in java that
Exception in thread "main" java.lang.NoSuchMethodError: main
Even if my class was just of 3 line of code.
public class Test{
public static void main(String[] args){
System.out.println("hello");
}
}
I was wondering why this happens, but later on i get to know there was a public class String which i had tried & created in same package.
so now new question arise is what happen in this kind of situation though String is not a keyword defined in java (you can use in your code)
Then I just deleted String.java & String.class file from the package but it sounds odd that you could not use String class as well.
Question: Does java gives major priority to our custom class?

Your main method needs to match
public static void main(java.lang.String[] args){ ... }
If you create your own String class in the same package where the class with your main method is, it will become
public static void main(your.own.package.String[] args){ ... }
which is valid, but will not allow the runtime launcher to find a main method anymore, since it expects java.lang.String[] as parameter.
The classes from java.lang are imported automatically by default, so you don't need an explicit import statement - that probably made it even more confusing to you.
As a rule of thumb, I would avoid to name my own classes the same as classes from the Java Runtime, whenever possible - especially from java.lang.
See also the JLS: Chapter 7. Packages:
A package consists of a number of compilation units (ยง7.3). A compilation unit automatically has access to all types declared in its package and also automatically imports all of the public types declared in the predefined package java.lang.

You can always use a fully qualified name:
public static void main(java.lang.String[] args) ...
The story you are telling says that we can use String as the name for one of our classes. But, like in real life, if there are two people named "John" around, you sometimes need to disambiguate them.

Related

Can one java class/file be part of more than one package?

I'm a relative beginner to Java, and I was just learning about packages and access restrictions, so I was wondering if it was possible to have one Java class belong to more than one package.
I don't mean sub-packages.
Technically you can have a same class with same content in two different packages but then when you use these 2 classes in another Java class then you would have to be very specific (absolute package name) when using either of the class.
Let me give an example ...
Here is class Testing which has exactly same members but are defined in two different packages i.e. com.overflow.stack and com.stack.overflow.
When they are used in an another class Test, you have to import both of them and use absolute package name for at least one of the Testing class so that Java compiler understand which instance is which class (alternatively you can use absolute package name for both the Testing class instances).
--
package com.overflow.stack;
public class Testing {
public void whoAmI() {
System.out.println(this.getClass().getCanonicalName());
}
}
--
package com.stack.overflow;
public class Testing {
public void whoAmI() {
System.out.println(this.getClass().getCanonicalName());
}
}
--
package com.stackoverflow;
import com.overflow.stack.Testing;
public class Test {
public static void main(String[] args) {
// not using absolute package name
Testing test1 = new Testing();
test1.whoAmI();
// must use absolute package name if want to use Testing class
// from different package then above.
com.stack.overflow.Testing test2 = new com.stack.overflow.Testing();
test2.whoAmI();
}
}
Sample Run:
com.overflow.stack.Testing
com.stack.overflow.Testing
That being said, if you or your team or organization is the author of this class then you should avoid having copies of classes in different packages as it will lead to redundant code duplication and will be very confusing for the consumers of these classes. Also it is highly possible that these copies will get out of sync and possibly lead to RuntimeException which are difficult to debug and can crash the application.
No, it cannot be.
But however there can be classes with same name in different packages, but no two similarly named classes in the same package.
You cannot put package declaration twice in the same class.
The package statement must be the first line in the source file. There can be only one package statement in each source file, and it applies to all types in the file.
However you can define same classes - same name and even same implementation in two packages but package name must be different.
Read more about packages here
You can declare a class with the same name in other packages.
It's not best practice of designing an application.

Default Classes imported in java

I have a simple code:
public class Hello
{
public static void main(String[] args)
{
System.out.println("Hello World");
}
}
I know that Object class is imported by default in every java program, but I wanted to ask whether PrintStream class is also imported by default if we are using print() or println() functions?
Because Object class belongs to java.lang package and PrintStream class belongs to java.io package, so if it is not imported by default, then how we are able to use the println() method of PrintStream class?
If it (PrintStream class) is not imported by default, then why the decompiler is importing it?
This is the output after decompiling it:
The types of intermediate expressions in your Java program do not need to be imported on the source code level. It's only when you assign the value of such an expression to a declared variable that you have to make its type explicit; at that moment you have to add the import (or use the qualified name).
In your case, System.out is such an intermediate expression; its type is indeed java.io.PrintStream, which is not imported by default as it is not in java.lang. If you would modify your class to
import java.io.PrintStream;
public class Hello {
public static void main(String[] args)
{
PrintStream myOut = System.out;
myOut.println("Hello World");
}
}
you need to add the import statement, or use the qualified name as in
public class Hello {
public static void main(String[] args)
{
java.io.PrintStream myOut = System.out;
myOut.println("Hello World");
}
}
On the bytecode level the story is different: since all dependencies need to be loaded for the JVM to be able to execute the code, all of them are listed in the .class file, including the types of intermediate expressions. Apparently the decompiler used in the screenshot of the OP isn't clever enough to realise that such imports are unnecessary on the source code level, and so it just creates import statements for all dependencies listed in the .class file.
I wanted to ask whether PrintStream class is also imported by default if we are using print() or println() functions
No, from the JLS:
A compilation unit automatically has access to all types declared in its package and also automatically imports all of the public types declared in the predefined package java.lang.
So you can use System because it belongs to java.lang.
so if it is not imported by default,then how we are able to use the println() method of PrintStream class?
Because System.out is accessible to your type, so you can use all visible method of System.out
why the decompiler is importing it
Looks like a bug in the decompiler you are using. This import is completely unnecessary here.
You can program without imports at all, just using the fully-qualified class names like this:
java.io.PrintStream out = System.out;
Imports are used just for convenience, so you can use simple class names in your code. It's possible that the same simple name appears in different packages (for example, java.awt.List and java.util.List) so to resolve this ambiguity you have to either use full class name or import the one you want (in case you want to use both of them, you will still have to use the full name for one of them). As you correctly mentioned, only classes from java.lang are imported always by default. Again, this is done for convenience, so you can use just System instead of java.lang.System (though java.lang.System.out.println() is also valid).
In your example as you don't directly mention the PrintStream in the source, no need to import it. Imports have nothing in common with class loading (which happens in runtime, not during the compilation).

Why a class containg a main method doesn't need to be public in Java? [duplicate]

This question already has answers here:
Package-private class within a .java file - why is it accessible?
(4 answers)
Java compilation of a .java file without a public class
(6 answers)
Closed 9 years ago.
I wrote the following code
class Hello //Note the class is not public
{
public static void main(String args[]) {
System.out.println("Hello");
}
}
So, when I run it, it runs fine and prints the output "Hello".
However, if JVM spec mandates that main method should be public since "it can't see main otherwise", shouldn't it apply to the class as well? If the JVM "can't see" Hello.main() when it is not declared public, how is it able to see the class A itself.
Is there any explanation for this other than "because the specification says so"?
And if the JVM is able to see all classes and methods as it is the "security/visibility enforcer" itself then why does the main method needs to be declared as public.
Just for kicks, a demo that private classes can also hold main:
class Outer {
private static class Inner {
public static void main(String[] args) {
System.out.println("Hello from Inner!");
}
}
}
Compiles and runs fine from the command line:
C:\junk>javac Outer.java
C:\junk>java Outer$Inner
Hello from Inner!
C:\junk>
if JVM spec mandates that main method should be public since "it can't
see main otherwise"
It can see but it doesn't see it as the entry point and that is why it gives NoSuchMethodError: main if you try to execute a class having no such method.
By classic design, the main entry point-
Must be named main
Must be public
Must be static
Must be void
Must have one argument that is an array of string
Hence,
public static void main(String args[])
Being static, JVM can call it without creating any instance of class which contains the main method. Not sure if it is the main reason for main being static by design.
A class with default access like Hello in your example is only visible to other classes in the same package.
I don't think the specification says that the class has to be Public.
Refer to the examples on the official java tutorial. None of the classes with main method in the examples are declared as Public.
This was discussed previously on stackoverflow. Refer: Package-private class within a .java file - why is it accessible?
Explains it well.
Mind that main is an early language feature. My guess is that it was thought that a private method could disappear in the .class file, maybe inlined, maybe given a shorter name. So it is a simple overrestricting (?) convention for retrieval of the correct method:
static void main(String[])
the default access specifier is package.Classes can access the members of other classes in the same package.but outside the package it appears as private but JVM has access to all the classes thus JVM can alter the visibility just to find the beginning of the program thus it makes it default by default
Of so first let's consider this
1. Since main method is static Java virtual Machine can call it without creating any instance of class which contains main method.
this:
2.Anything which is declared in class in Java comes under reference type and requires object to be created before using them but static method and static data are loaded into separate memory inside JVM called context which is created when a class is loaded. If main method is static than it will be loaded in JVM context and are available to execution.
and finally this:
3. Main method is entry point for any Core Java program. Execution starts from main method.
So in conclusion: Java first charge your Main method, the public make this method accessible from everywhere for the JVM, and static set the method in the JVM context so the first thing that the JVM loads it's your main method!
Class Hello{}
just make your class accessible to all classes from the same package.
Here's a similar question with quite a straightforward answer.
Basically, the JVM can access the main in any class that is either of default access or of public access because it is the entry point. If the class is private or protected you will get a compile error.
when JVM starts it loads the class specified in the command line (see the jls java virtual machine start up), and you cannot have protected or private specifier in the class so the only option for you is to either have public or just blank default and both these access specifier allows the class to be accessed inside the same package. So there is no need for specifying public keyword for the class to load.
Hope its clear.

Java compilation of a .java file without a public class

Okay, so a java source file must have at least one public class and the file should be called "class-name.java". Fair enough.
Hence, if I have a class, then the following would compile:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!"); // Display the string.
}
}
But what bugs me is that if I remove the 'public' access modifier from the above code, the code still compiles. I just don't get it. Removing it, the code looks like:
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!"); // Display the string.
}
}
In the above code, since I removed the public access modifier, my class has default or package access, i.e. it can't be accessed from the outside world, only from within the package.
So my question is, how does the above code compile ? The file HelloWorld.java in this case does not have a public HelloWorld class (only a package-private HelloWorld.class) and thus to my understanding should not compile.
a java source file must have at least one public class and the file should be called class-name.java
Incorrect, a top level class does not have to be declared public. The JLS states;
If a top level class or interface type is not declared public, then it may be accessed only from within the package in which it is declared.
See http://java.sun.com/docs/books/jls/second_edition/html/names.doc.html#104285 section 6.6.1.
You can place non-public class in a file, and it's not a bug but feature.
Your problem is on level of packaging, not compile. Because you can compile this file with non-public class, but you can't call it from outside, so it's not working as application base class
Like this:
// [+] single file: SomeWrapper.java
public class SomeWrapper {
ArrayList<_PrivateDataType> pdt;
}
// [-] single file: SomeWrapper.java
// [+] single file: _PrivateDataType.java
class _PrivateDataType {
// members, functions, whatever goes here
}
// [-] single file: _PrivateDataType.java
A main method is just like any other method. The only difference is that it may be invoked from the command line with the java command. Even if the main method is not visible from the command line, the class can still be used like any other Java class, and your main method may be invoked by another class in the same package. Therefore i makes sense that it compiles.
In Java main function are not special in any sense. There just exists a terminal command that is able to invoke static methods called main...
There are valid usages for a non public classes. So the compiler does not give error when you try to compile the file.
That's nothing to wonder about. I suppose this behavior is similar to the one of some C/C++-compiler.
Code like "void main() { /.../ }" will be compiled correctly by those compilers, although it is not standards-compliant code. Simply said, the compiler exchanges the "void" with "int".
I think a similar behavior is implemented by the java compiler.
When you do not specify the access modifier of the class (or its field or method), it is assigned "default" access. This means it is only accessible from within the same package (in this case, the default package).
The website Javabeginner.com has an article on the subject - you should become familiar with access modifiers in Java, either from this site, or others.

get static initialization block to run in a java without loading the class

I have a few classes as shown here
public class TrueFalseQuestion implements Question{
static{
QuestionFactory.registerType("TrueFalse", "Question");
}
public TrueFalseQuestion(){}
}
...
public class QuestionFactory {
static final HashMap<String, String > map = new HashMap<String,String>();
public static void registerType(String questionName, String ques ) {
map.put(questionName, ques);
}
}
public class FactoryTester {
public static void main(String[] args) {
System.out.println(QuestionFactory.map.size());
// This prints 0. I want it to print 1
}
}
How can I change TrueFalseQuestion class so that the static method is always run so that I get 1 instead of 0 when I run my main method? I do not want any change in the main method.
I am actually trying to implement the factory patterns where the subclasses register with the factory but i have simplified the code for this question.
You can call:
Class.forName("yourpackage.TrueFalseQuestion");
this will load the class without you actually touching it, and will execute the static initializer block.
To register the TrueFalseQuestion class with the factory, its static initializer needs to be called. To execute the static initializer of the TrueFalseQuestion class, the class needs to either be referenced or it needs to be loaded by reflection before QuestionFactory.map.size() is called. If you want to leave the main method untouched, you have to reference it or load it by reflection in the QuestionFactory static initializer. I don't think this is a good idea, but I'll just answer your question :) If you don't mind the QuestionFactory knowing about all classes that implement Question to construct them, you can just reference them directly or load them through reflection. Something like:
public class QuestionFactory {
static final HashMap<String, String > map = new HashMap<String,String>();
static {
this.getClassLoader().loadClass("TrueFalseQuestion");
this.getClassLoader().loadClass("AnotherTypeOfQuestion"); // etc.
}
public static void registerType(String questionName, String ques ) {
map.put(questionName, ques);
}
}
Make sure map's declaration and construction is before the static block. If you don't want QuestionFactory to have any knowledge of the implementations of Question, you'll have to list them in a configuration file that gets loaded by QuestionFactory. The only other (possibly insane) way I could think to do it, would be to look through the entire classpath for classes that implement Question :) That might work better if all classes that implemented Question were required to belong to the same package -- NOTE: I am not endorsing this solution ;)
The reason I don't think doing any of this in the QuestionFactory static initializer is because classes like TrueFalseQuestion have their own static initializer that calls into QuestionFactory, which at that point is an incompletely constructed object, which is just asking for trouble. Having a configuration file that simply lists the classes that you want QuestionFactory to know how to construct, then registering them in its constructor is a fine solution, but it would mean changing your main method.
The static initializer for the class can't be executed if the class is never loaded.
So you either need to load all the correct classes (which will be hard, since you don't know them all at compile time) or get rid of the requirement for the static initializer.
One way to do the latter is to use the ServiceLoader.
With the ServiceLoader you simply put a file in META-INF/services/package.Question and list all implementations. You can have multiple such files, one per .jar file. This way you can easily ship additional Question implementations separate from your main program.
In the QuestionFactory you can then simply use ServiceLodaer.load(Question.class) to get a ServiceLoader, which implements Iterable<Question> and can be used like this:
for (Question q : ServiceLoader.load(Question.class)) {
System.out.println(q);
}
In order to run the static initializers, the classes need to be loaded. For this to happen, either your "main" class must depend (directly or indirectly) on the classes, or it must directly or indirectly cause them to be loaded dynamically; e.g. using Class.forName(...).
I think you are trying to avoid dependencies embedded in your source code. So static dependencies are unacceptable, and calls to Class.forName(...) with hard-coded class names are unacceptable as well.
This leaves you two alternatives:
Write some messy code to iterate over the resource names in some package, and then use Class.forName(...) to load those resources that look like your classes. This approach is tricky if you have a complicated classpath, and impossible if your effective classpath includes a URLClassLoader with a remote URL (for example).
Create a file (e.g. a classloader resource) containing a list of the classnames that you want loaded, and write some simple code to read the file and use Class.forName(...) to load each one.

Categories