I'm using maven to build the project and compile failed because I put class Test2 in Test.java,
but is it because of maven or simply because java itself doesn't support this?
BTW,how can I open a maven project with eclipse?
A public class called ClassName must (in most cases) be defined in a file called ClassName.java.
Edit
Although this is not a requirement of the Java language, most (if not all) implementations of Java, the above mentioned relationship between the class name and file name must hold, or a compiler error will result.
(For more information, please refer to Jon Skeet's answer.)
The reason for this can be found by reading Section 7.2: Packages of The Java Language Specification, Third Edition.
In the section, it describes how the directory structure can be mapped to a fully-qualified class name in Java, which leads to a requirement that the .class file which contains the bytecode for a class must reside in a path that resembles that of the fully-qualified class name.
The original answer which incorrectly stated that the naming scheme is a requirement has been edited.
The Java Language Specification itself doesn't actually require this - but it explicitly allows file-system-based implementations to do so, and most do.
From section 7.6:
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.
When packages are stored in a database
(§7.2.2), the host system must not
impose such restrictions. In practice,
many programmers choose to put each
class or interface type in its own
compilation unit, whether or not it is
public or is referred to by code in
other compilation units.
For practical purposes I think it's reasonable to basically assume that it's required.
Java requires you to have your public class inside a file with the same name.
For eclipse and maven use sonatype m2 plugin. Inside your maven project you can then type
mvn eclipse:eclipse
and maven will create a .project and a .classpath file for you. These are the files eclipse needs to work with the project.
You have to define the eclipse classpath variable M2_REPO with the path of your local maven repository.
With sonatype m2 you can do maven things from within eclipse: add dependencies, run maven targets, ...
The connection between file name and class name is the following:
if you have public class in a file, the filename must be the same as the class name
you can have as many non-public classes as you want in a file with different names
I'm using maven to build the project and compile failed because I put class Test2 in Test.java,
Source files must be named after the public class they contain, appending the suffix .java. In you case, the source file for the public class Test2 must be Test2.java 1.
is it because of maven or simply because java itself doesn't support this?
The Java compiler, javac, is complaining, not Maven (Maven doesn't change the behavior of the compiler).
how can I open a maven project with eclipse?
Either use the Maven Eclipse Plugin (i.e. a plugin for Maven) and simply run mvn eclipse:eclipse on your project and then Import... it as Existing Projects into Workspace in Eclipse. You will need to set a classpath variable M2_REPO pointing to the local repository to use it. Check the Usage page for the details.
Or (and that's an exclusive or) install m2eclipse (i.e. a plugin for Eclipse that extends it to make it able to understand a Maven projects and interact with it in a bi-directional way) and Import... your project as an Existing Maven Projects.
If EXCLUSIVE is not clear enough, this means: use one or the other but not both in the same time.
1 As mentioned by Jon Skeet, the JLS allows this restriction for file-based implementations. This doesn't apply when using a database to store Java constructs (like Visual Age for Java was doing). But in your case, it does.
Related
I am using different libraries that reference the same library in different versions with different group-ids (relocated). So maven assumes that those are different libraries and puts them both in classpath.
Nevertheless the package-names have not changed, so the same class with the same package-name exist in maven.
This is e.g. the case with org.bouncycastle:bcmail-jdk14-1.38 vs. org.bouncycastle:bcmail-jdk14-138. But since both versions are identical I don't expect trouble.
But with javax.xml.stream:stax-api-1.0-2 vs. stax:stax-api-1.0.1 we have no identical bytecode, so the same class with different content will be in the classpath.
Am I right - and if so, can maven warn me and prevent such problems?
You can use the enforcer rule
https://www.mojohaus.org/extra-enforcer-rules/banDuplicateClasses.html
that allows you to break the build if a class name appears in more than one jar.
No, for Maven those are different artifacts and you can get into trouble. Having multiple versions of the same class on the class path is not a good idea.
It seems that in Java 9 it is not allowed to have so-called Split Packages, i.e. the same package being defined in two different modules. This causes a problem with my migration process: The (Gradle) project contains a Jar file that is called bootstrap.jar, with a structure like this:
bootstrap.jar
- com
- example
- Foo.class
- Bar.class
- Baz.class
The src directory contains a class com.example.Bar that depends on Foo as well as a module definition, for com.example. The bootstrap.jar file does not contain a module info, as it was compiled before Java 9, so it uses an automatic module called bootstrap. The problem is that now the package com.example is defined in both modules, com.example and bootstrap.
The reason there is this bootstrap.jar file, to begin with, is as follows:
The src/com/example folder actually contains Bar.java, Baz.java and another file, Foo.dyvil. The latter is written in a JVM-based programming language. So the dependency chain looks like this:
Bar.java -> Foo.dyvil -> Baz.java
During the build process, it gets compiled to Foo.class, which gets placed in a new Jar file that later replaces bootstrap.jar. The reason all these files are placed is that both the Java and Dyvil compiler cannot process the other languages files, so they require some access to the compiled classes from the previous build. So that is why there is bootstrap.jar.
Now for the actual problem: Since split packages are disallowed in Java 9, is there any way to achieve "split builds" using "bootstrap" jar files as described and used in my project? Or is there any other approach?
Though the long-term solution to this is resolving such packages to exist in a single module and then modularising the code.
As a temporary solution, you can make use of the option:-
--patch-module <module>=<file>(<pathsep><file>)*
as in your case
--patch-module com.example=bootstrap.jar
Do keep in mind though, the --patch-module option is intended only for testing and debugging. Its use in production settings is strongly discouraged.
I find a project in Eclipse has it own class path.
If i use maven create a new web project.
System.getProperty("java.class.path");
When i print the result,
I find the class path contains G:\newtool\workspace\springmvc\target\classes.
Who can explain the principles behind it.Why the class path is this directory.
Is the build function of Eclipse same as the command,javac -classpath?
And i find another question.
public class KnightMain {
public static void main(String[] args) throws Exception {
System.setProperty("java.class.path","G:/newtool/workspace;G:/newtool");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("knight.xml");
Knight knight = context.getBean(Knight.class);
knight.embarkOnQuest();
String s[] = System.getProperty("java.class.path").split(";");
for (String string : s) {
System.out.println(string);
}
context.close();
}
}
Although i set the class path to other directory where the knight.xml is not exist.But ClassPathXmlApplicationContext find it finally.Why the
System.setProperty("java.class.path","G:/newtool/workspace;G:/newtool");
makes no difference.Although the print result is:
G:/newtool/workspace G:/newtool
Two different tools, two different concepts.
First of all eclipse has its own java compiler. It is not using javac in any way. And the class path used by the eclipse compiler, is, surprise, what you told it to be.
In other words: when you create your eclipse projects, you configure its build path. The Build Path determines which libraries, other projects, ... should be imported, exported, ... and so on.
Whereas, when you open your command like shell, and you call javac directly, the classpath is based on the settings that you make there; for example by calling
javac -classpath /some/directory/with/classes:/some/bla.jar
Or in your case: you are using maven, which comes with its pre-defined rules, project dependencies, and so on. Thus your classpath there depends on the conventions/rules that maven applies for "java web projects". Thus: if you want to understand what maven is doing for you: you have to study the maven documentation for the features you are using there!
EDIT: I think what you are actually trying can't work. I think that this specific system property is more of a "read only" value. Meaning: you can use it to understand the current classpath. But writing the property will not change the classpath of the JVM you are currently running in.
Actually, that makes a lot of sense: if any piece of java code could change the classpath on the fly, that screams "security problem" all over the place! As that would allow you to completely change where the JVM would be loading its classes from.
The java.class.path property is used by JVM to locate classes and JAR files for loading. This system property is common for most available JVMs including Oracle and IBM implementations. This property is used by the default class loader, but not all custom class loaders. You can implement your own class loader, that ignores java.class.path and is using some other property to locate loader-specific packages. One example is Eclipse. Eclipse core has a custom class loader that is not using java.class.path.
Today I started learning Java.
I saw that package automatic gets included in .Java file.
I was wondering if it always need to be included?
Consider specify a common package for all the types within a same project.
In Java is common to start a project with a specific package setting. A package creates a namespace to disambiguate the types that it includes, to play nicelly with other projects that may or may not be in the same classpath. Normally, the package is bound to a URL of the project.
Think of Java packages like C++ namespaces.
A huge project/product written in Java can depend on lots and lots of projects, each described in a different package.
Organizations like Apache have lots of projects, organized under a common package pattern: org.apache.<<name_of_the_project>>.
Consider starting your project with a package named: com.user3552670; or something like your personal site, so persons that will consume your project can relate to the creator.
Yes and no.
It's used to specify the package of the class, read more here.
You could create a class without a package, but your code will look bad..
They exists to avoid conflicts, example between your code and default java package.
If packages doesn't exists, you can't create a class named ArrayList because already exists in Java.
Some IDEs force the fact that, if your .java file is in com/a/b/c folder his package should be com/a/b/c (If i don't remember wrong, IntellIJ IDEA do that)
Yes and no.
It must be there, but the IDE takes care of it (I don't use Netbeans, but I'd bet that it can do it, too). When moving files between packages, it has to be updated, but again, the IDE does it all.
In Eclipse 3.5, say I have a package structure like this:
tom.package1
tom.package1.packageA
tom.package1.packageB
if I right click on an the tom.package1 package and go to Refactor->Rename, an option "Rename subpackages" appears as a checkbox. If I select it, and then rename tom.package1 to tom.red my package structure ends up like this:
tom.red
tom.red.packageA
tom.red.packageB
Yet I hear that Java's packages are not hierarchical. The Java Tutorials back that up (see the section on Apparent Hierarchies of Packages). It certainly seems like Eclipse is treating packages as hierarchical in this case.
I was curious why access specifiers couldn't allow/restrict access to "sub-packages" in a previous question because I KNEW I had seen "sub-packages" referenced somewhere before.
So are Eclipse's refactoring tools intentionally misleading impressionable young minds by furthering the "sub-package" myth? Or am I misinterpreting something here?
Eclipse can't possibly violate the JLS in this case, because it has nothing to do with compiling or running Java source or bytecode.
The refactoring tools behave as they do because that behaviour is useful to developers. The behaviour is useful to developers because, for many intents and purposes, we do treat packages as hierarchal (a.b.c has some kind of relationship with a.b, even if that relationship is not consistent from project to project). That doesn't mean Java treats them as hierarchal intrinsically.
One example where people treat packages as very hierarchal is in configuring a logging framework such as log4j. Again, it's not intrinsic to log4j, but that's how people use it in practice.
Java packages are not hierarchical in the sense that importing everything from package A does not import everything from package A.B.
However, Java packages do correspond directly to the directory structure on the file system, and directories are hierarchical. So Eclipse is doing the correct thing - it is renaming the directory, which automatically changes the name of the parent directory of the renamed directory's children (to state the very obvious).
even java itself has the concept of subpackage:
http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/java.html
java -ea[:<package name>"..." | :<class name> ]
Enable assertions. Assertions are disabled by default.
With no arguments, enableassertions or -ea enables assertions. With one argument ending in "...", the switch enables assertions in the specified package and any subpackages. If the argument is simply "...", the switch enables assertions in the unnamed package in the current working directory. With one argument not ending in "...", the switch enables assertions in the specified class.
If a single command line contains multiple instances of these switches, they are processed in order before loading any classes. So, for example, to run a program with assertions enabled only in package com.wombat.fruitbat (and any subpackages), the following command could be used:
java -ea:com.wombat.fruitbat... <Main Class>
Java's packages are not hierarchical, but Eclipse stores packages on your system's file structure.
tom.package1.packageA is represented on a Windows file system as tom/package1/packageA.
When you ask Eclipse to refactor a package name, you're asking Eclipse to change the name of the file system directory structure.
You can have packages in Eclipse like:
tom.package1.packageA
tom.package2.packageB
tom.package3.packageC
You'll just have different 2nd level file system directories.