I have my own System class with a Test class in the same package which test methods declared in the System class. I also have created a System constructor which takes 3 parameters. When I created a constructor to test the methods in my IDE the program was working fine (I had use java.util.System where I need to use the System. methods) but IDE knew I was referring to my own class when I created the constructor. However, when I trying running my test class from command line it won't even compile:
error: constructor System in class System cannot be applied to given types;
System sys = new System("String1", "String2", 20);
^
required: no arguments
found: String,String,int
reason: actual and formal argument lists differ in length
My guess is that instead of my constructor, the java.util.System constructor (with no parameters) is being invoked which causes the whole program to crash. Does anyone know how to fix it and why is it only happening in command line and not in IDE?
You mention java.util.System, but that's not where the platform's System lives; it lives in java.lang.
This is a problem. Java code acts as if import java.lang.*; is at the top of every file, even if you don't write it. The java language spec says so. So now you get into a fun dilemma:
Given a class named System in the same package, and you star-imported another package that also has a System class in it, which one is chosen if you use an unqualified type reference "System" someplace in the code?
The answer is presumably that whilst the spec is clear on this, few to no java coders care about the answer. They'd rather just.. not get into this bizarro situation. Thus, don't use star imports lightly, and don't name any classes the same as classes in the java.lang package.
If you must know, the order is as follows:
To resolve the type name System into which actual type it is referring to:
Check if there is a named (non-star) import for it: import java.lang.System;
Check if there is a class named System in this source file.
Check if there is a class named System in this package.
Check if there is a class named System in any star-imported package (and therefore, in java.lang as that is always star-imported.
Thus, given that it sounds like your System class is in the same package, that one 'wins'. However, if during a compilation run your non-test source files (your System.java file) is not on the classpath or sourcepath, then instead of the compiler straight up telling you this, instead you get the error you witness.
So, you have 2 problems:
you are not compiling the test classes on the command line correctly. Use a build system.
Don't name classes the same as classes in the lang package; whilst you can make code that works, and the ordering is well defined, it's confusing (hey, it confused you - that's anecdotal evidence right there!) and not idiomatic java. Other folks will have a very hard time reading your code, and you're likely to run into bugs in IDEs and such, because when you're doing weird unique things, odds go way up you run into scenarios nobody thought of and nobody ran into before.
Related
Object Oriented programming
sorry for the lack of clarity.
our teacher gave us this example its a singleton and factory pattern program combined however when I run it in java it keeps telling me that the class fromExperian doesn't exist. I've retyped it word for word in eclipse and double checked for anything different it's one program all in the same file.
the issue:
I get an error message saying that the class doesn't exist even when it does.
okay so this is the pdf document each screen shot is a page. So if I type into the scanner in the main I'll get fromExperian class doesn't exist, or fromTransUnion class doesn't exist etc.
It looks like it can't find the classes even though they are in the same file?
Your code works for me. But only as long as it exists in the default package!
You have to use Class.forName(...) with the canonical class name. So as long as you are not in the default package your error occurs.
penCheck = (pen)Class.forName(s).newInstance();
leads to your error if your class does not lie in the default package.
penCheck = (pen)Class.forName(fromExperian.class.getCanonicalName()).newInstance();
instead will always work.
And yes it also works when fromExperian is abstract.
When you set the company to Experian, you then try to instantiate the fromExperian class. That can't happen, as fromExperian is abstract.
You'll have to make your fromExperian class concrete by removing the abstract keyword, or create at least a concrete class named (which name starts with "from") that extends fromExperian and set the company name accordingly.
I am not sure where your files are. Make sure all your .java files are in the proper spots. I don't know the details but when you get this kind of error I believe it's because the JVM can't find the .class file that the compiler was supposed to have made. When you compile it check your classpath and make sure everything is in the right packages and what not. Your single_factory_pattern.class or fromExperian.class is the culprit.
As the title already says, I would like to know if it is somehow possible to give a class a different filename in Java with Eclipse ?
Edit: I only want to know if its possible with Eclipse. If you don't know the answer, please resist the urge to respond with condescending answers.
Edit2: It's hilarious what kind of responses I get here. All I wanted to know is if it is possible to have a class with a different filename (and I meant the public class) and nothing else. I thought this is the kind of forum to ask these questions, but the second response I got was already an insult. Is this some kind of taboo question or what is going on ?
Your filename should always match your class name, end of story. Although the JLS doesn't specifically state that it HAS to be done, they leave it up to the implementation of the compiler to make that decision. I'm pretty sure most (if not all) will not allow you to differ from that standard.
The JLS states:
When packages are stored in a file system (§7.2.1), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such type per compilation unit. This restriction makes it easy for a compiler for the Java programming language or an implementation of the Java virtual machine to find a named class within a package; for example, the source code for a public type wet.sprocket.Toad would be found in a file Toad.java in the directory wet/sprocket, and the corresponding object code would be found in the file Toad.class in the same directory.
So while you may be able to rename the file itself in eclipse, or your filesystem - you will more than likely hit a compile error.
I don't know why you would like to do that but it is possible if you compile files from command line with help of symbolic links.
Let's say you have class YourClass saved in a file OtherName.java. If you create a symbolic link to that file like this:
UNIX system: (for sure doesn't work on Solaris - other system aren't verified)
ln -s OtherName.java YourClass.java
javac YourClass.java
WINDOWS system: (works on Windows Vista/2008+)
mklink YourClass.java OtherName.java
javac YourClass.java
the compiler finds the type and compilation works...
This solution is not verified on Unix systems, but works for sure on Windows Vista/2008+..
What does Eclipse have with the naming conventions or rules of Java Programming Language?
Eclipse is just an IDE, and if you are working with Java you have to obey its rules.
Lets's say you have X.java file. This means that you can have only one public / abstract / final class named X in this file. There is no limitation on the number of classes and their names and also their nesting relations with each other as far as no more than one class holds the filename as its class name. If a class takes the filename, then it should have one or more of these modifiers: public, static, final. That's the story.
No, the Java a public class and the file must have the same name.
If you try to give the class another name, the compiler will fail with
class YourClass is public, should be declared in a file named YourClass.java
But you can declare additional private classes in a file which contains a public class.
below are the situations where you can have different class name.
1.class is not public class and exists in a java file where atleast one public class is defined
class notpublic{
}
public class PublicClass {
}
2.Class is a InnerClass .
public class PublicClass {
class InnerClass{
}
}
The error I get is exactly the error specified in:
http://java.syntaxerrors.info/index.php?title=Own_file
(class must be defined in its own file.)
but they don't give a solution there how to solve it, other than just having a file per public class.
Thank you, eclipse, for making me do this, but this is not mandatory in Java. Is there a way to get rid of this error?
Yes, it is mandatory in Java. Each public class has to be in a separate file named exactly the same way as the class.
See this question about it. The Java language specification writes that this is not 100% mandatory for compilers, but they usually do that. And since it is a good thing, and is noted in the spec, all compilers do it.
When packages are stored in a file system (§7.2.1), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav)
If you want to have multiple classes in the same file, that's a different story. You can do it in two ways:
declare them as package-private classes with class Foo after the body of the main class. You can have any number of non-public classes in the same file
declare them as static inner classes: public static class InnerFoo inside the main class body. That way they will be visible to other classes by FooClass.InnerFoo
we can declare only one public file in a source file and file name must match the public class name
is there any reason to this restriction....
Well, it's not a compulsory restriction in Java. It's one that the Java Language Specification mentions as an option. From section 7.6 of the JLS:
When packages are stored in a file system (§7.2.1), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such type per compilation unit. This restriction makes it easy for a compiler for the Java programming language or an implementation of the Java virtual machine to find a named class within a package; for example, the source code for a public type wet.sprocket.Toad would be found in a file Toad.java in the directory wet/sprocket, and the corresponding object code would be found in the file Toad.class in the same directory.
But basically it's there to encourage you to make your source easier to navigate. If you know the name of a public class, it's usually pretty easy to find the source code for it.
Yes, it's the specification of the Java language...
The reason is, that this is the convention. Also the classloader expects a class in a specific file. You can write your own classloader to avoid this restriction, but there is no good reason to do this. Everyone looking on your code will get confused. ;)
However, you can create "multiple" classes in one file by creating inner classes. I know, its not the same, but usually you should think about more important things than why there is only one class in one file.
It's there so that the compiler can find the source code of dependent classes.
#saravanan. I have executed some simple programs which show that just a single default class(ie a class with no access specifier) having the main method works well in java when u save the file name with the default class name.
To add on to the reason of naming the file with public class name, in a document I went through the details into this state that the JVM looks for the public class (since no restrictions and can be accessible from any where) and also looks for public static void main() in the public class .
This public class acts as the initial class from where the JVM instance for the java application( program) is begun.So when u provide more than one public class in a program the compiler itself stops you by throwing an error.
This is because later you can't confuse the JVM as to which class to be its initial class because only one public class with the public static void main(String args[]) is the initial class for JVM.
HOPE I have helped you in understanding JAVA programming naming better.
simply remember only that class would be public which has the main other files dont be public
I created a class "String" and placed that in package "java" [ actually i wanted to create java.lang to see which class is loaded by classLoader as
Once a class is loaded into a JVM, the
same class (I repeat, the same class)
will not be loaded again
quoted from oreilly ] . But that thing later, why on running this class i am getting
java.lang.SecurityException: Prohibited package name: java
For which security reason java is not allowing me to have a class in java package? What one could do if there will not be no such check?
User code is never allowed to put classes into one of the standard Java packages. That way, user code cannot access any package-private classes/methods/fields in the Java implementation. Some of those package-private objects allow access to JVM internals. (I'm thinking of SharedSecrets in particular.)
Firstly, these types of restrictions are in place to enforce the Java sandbox. That is, running untrusted code in a trusted environment. Such as running an applet from some site (that you don't necessarily trust), on your computer (the trusted environment) in your browser. The intent is to disallow untrusted code from gaining access to package-private stuff which could help it escape the sandbox.
Normally these restrictions are enforced by the SecurityManager, so they shouldn't happen when you run your own application on the command-line (unless you explicitly specify to use a SecurityManager). When you control the environment, you could just go and edit the String.class definition inside the rt.jar of your Java (and you can, technically anyway, not sure what licensing says). As I said the restrictions are normally in the SecurityManager, but this particular rule about java.* packages is in the ClassLoader class.
To answer your question: My guess is that java.* check is there because of
a) historic reasons
b) somewhere in the Java core there's a check on the name of the class, something like: All class that start with java.* get special treatment.
However, consider that even if you managed to create a class called java.lang.String, it would not be the same class as the java.lang.String defined by the Java core. It would just be a class with the exact same name. Class identity is more than just the name of the class, even though this can be tricky to perceive unless you really play with ClassLoaders.
So a class loaded by the application classloader in the package java.lang, would not have access to the core java.lang package-private stuff.
To illustrate this, try to create a class called javax.swing.JButton with a main method and execute it. You'll get a java.lang.NoSuchMethodError: main. That's because java finds the "real" JButton before your class, and the real JButton doesn't have a main method.
In a Java standalone application you might be able to go around this restriction by calling one of the private native defineClassx methods directly via use of reflection and setAccessible.
BTW: The core java.lang.String is guaranteed to be loaded before your code ever executes because it's referenced everywhere, you would not get there first with your user code. The JVM gets set up to a degree before ever even trying to load your class, let alone execute it.
You cannot have "java.*" package names. This is actually hard-coded in the Java core so you cannot even grant a security manager permission to work around it (cf. ClassLoader::preDefineClass(...))
java is a reserved package name. Only classes inside the JVM can reside in this package.
If anyone could write in the Java package, that could result in libraries arbitrarily replacing core Java classes by their own implementations. That could result in a lot of thinks, from breaking core Java features to execution of malicious code.
A program could bypass security measures if a program could override JVM core classes with trojan versions. For example, String is used practically everywhere.
From the ClassLoader.defineClass(..) javadoc:
...The specified class name cannot begin with " java. ", since all classes in the " java.* packages can only be defined by the bootstrap class loader
and
Throws: ... SecurityException - If an attempt is made to add this class to a package that contains classes that were signed by a different set of certificates than this class, or if the class name begins with " java. ".
Probably during refactoring/patch applying/etc. you have added to package name word 'java', which is usually a folder that contains packages.
So you could end with the structure:
src->main->java->java.com.yourpackage.name
It might also happens for test:
src->main->test->java->java.com.yourpackage.name
Verify it in your IDE and remove "java." part
An excerpt from java.lang.ClassLoader's preDefineClass method:
/* Determine protection domain, and check that:
- not define java.* class,
- signer of this class matches signers for the rest of the classes in
package.
*/
private ProtectionDomain preDefineClass(String name,
ProtectionDomain pd)
{
...
// Note: Checking logic in java.lang.invoke.MemberName.checkForTypeAlias
// relies on the fact that spoofing is impossible if a class has a name
// of the form "java.*"
if ((name != null) && name.startsWith("java.")) {
throw new SecurityException
("Prohibited package name: " +
name.substring(0, name.lastIndexOf('.')));
}
...
}
Please note that java.lang.ClassLoader is an abstract class, meaning that a subclass (say, SecureClassLoader) will actually implement it. However, the preDefineClass method is private, so it cannot be overridden by a subclass.
preDefineClass is called by the defineClass method, which is protected final. This means defineClass is accessible to subclasses and they can call it, but they won't be able to change its implementation.