为新手解释的 Java 项目结构?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1953048/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 01:45:03  来源:igfitidea点击:

Java project structure explained for newbies?

javadevelopment-environment

提问by MalcomTucker

I come from a .NET background and am completely new to Java and am trying to get my head around the Java project structure.

我来自 .NET 背景,对 Java 完全陌生,我正在努力了解 Java 项目结构。

My typical .NET solution structure contains projects that denote logically distinct components, usually named using the format:

我的典型 .NET 解决方案结构包含表示逻辑上不同的组件的项目,通常使用以下格式命名:

MyCompany.SomeApplication.ProjectName

MyCompany.SomeApplication.ProjectName

The project name usually equals the root namespace for the project. I might break the namespace down further if it's a large project, but more often than not I see no need to namespace any further.

项目名称通常等于项目的根命名空间。如果它是一个大型项目,我可能会进一步分解命名空间,但通常我认为不需要进一步命名空间。

Now in Java, you have applications consisting of projects, and then you have a new logical level - the package. What is a package? What should it contain? How do you namespace within this App.Project.Packagestructure? Where do JARs fit into all this? Basically, can someone provide a newbies intro to Java application structure?

现在在 Java 中,您拥有由项目组成的应用程序,然后您拥有一个新的逻辑级别 - 包。什么是包?它应该包含什么?你如何在这个App.Project.Package结构中命名空间?JAR 在哪里适合所有这些?基本上,有人可以提供 Java 应用程序结构的新手介绍吗?

Thanks!

谢谢!

Edit:Some really cracking answers thanks guys. A couple of followup questions then:

编辑:一些真正破解的答案谢谢大家。然后有几个后续问题:

  • Do .JAR files contain compiled code? Or just compressed source code files?
  • Is there a good reason why package names are all lower case?
  • Can Packages have 'circular dependencies'? In other words, can Package.A use Package.B and vice versa?
  • Can anyone just show the typical syntax for declaring a class as being in a package and declaring that you wish to reference another package in a class (a using statement maybe?)
  • .JAR 文件是否包含已编译的代码?或者只是压缩的源代码文件?
  • 包名全部小写是否有充分的理由?
  • 包可以有“循环依赖”吗?换句话说,Package.A 可以使用 Package.B,反之亦然吗?
  • 任何人都可以展示用于将类声明为在包中并声明您希望引用类中的另一个包的典型语法(可能是 using 语句?)

采纳答案by Carl Smotricz

"Simple" J2SE projects

“简单”的 J2SE 项目

As cletus explained, source directory structure is directly equivalent to package structure, and that's essentially built into Java. Everything else is a bit less clear-cut.

正如 cletus 所解释的那样,源目录结构直接等同于包结构,这本质上是内置于 Java 中的。其他一切都不太明确。

A lot of simple projects are organized by hand, so people get to pick a structure they feel OK with. What's often done (and this is also reflected by the structure of projects in Eclipse, a very dominant Java tool) is to have your source tree begin in a directory called src. Your package-less source files would sit directly in src, and your package hierarchy, typically starting with a comdirectory, would likewise be contained in src. If you CDto the srcdirectory before firing up the javaccompiler, your compiled .classfiles will end up in the same directory structure, with each .class file sitting in the same directory and next to its .javafile.

许多简单的项目都是手工组织的,所以人们可以选择一个他们觉得合适的结构。经常做的事情(这也反映在 Eclipse 中的项目结构中,这是一个非常重要的 Java 工具)是让源代码树从一个名为src. 您的无包源文件将直接位于 src 中,您的包层次结构(通常以com目录开头)同样包含在src. 如果您在启动编译器之前CD访问该src目录javac,您编译的.class文件将在相同的目录结构中结束,每个 .class 文件都位于同一目录中并位于其.java文件旁边。

If you have a lot of source and class files, you'll want to separate them out from each other to reduce clutter. Manual and Eclipse organization often place a binor classesdirectory parallel to srcso the .class files end up in a hierarchy that mirrors that of src.

如果您有很多源文件和类文件,您需要将它们彼此分开以减少混乱。Manual 和 Eclipse 组织通常将binclasses目录平行放置,src因此 .class 文件最终处于与 .class 文件镜像的层次结构中src

If your project has a set of .jarfiles to deliver capability from third-party libraries, then a third directory, typically lib, is placed parallel to srcand bin. Everything in libneeds to be put on the classpath for compilation and execution.

如果您的项目有一组.jar文件来提供来自第三方库的功能,那么第三个目录(通常lib是 )与src和平行放置bin。中的所有内容都lib需要放在类路径上以进行编译和执行。

Finally, there's a bunch of this and that which is more or less optional:

最后,有一堆这个和那个或多或少是可选的:

  • docs in doc
  • resources in resources
  • data in data
  • configuration in conf...
  • 文档在 doc
  • 资源在 resources
  • 数据在 data
  • 配置在conf...

You get the idea. The compiler doesn't care about these directories, they're just ways for you to organize (or confuse) yourself.

你明白了。编译器不关心这些目录,它们只是您组织(或混淆)自己的方式。

J2EE projects

J2EE项目

J2EE is roughly equivalent to ASP.NET, it's a massive (standard) framework for organizing Web applications. While you can develop your code for J2EE projects any way you like, there is a firm standard for the structure that a Web container will expect your application delivered in. And that structure tends to reflect back a bit to the source layout as well. Here is a page that details project structures for Java projects in general (they don't agree very much with what I wrote above) and for J2EE projects in particular:

J2EE 大致相当于 ASP.NET,它是一个用于组织 Web 应用程序的大型(标准)框架。虽然您可以按照自己喜欢的任何方式为 J2EE 项目开发代码,但对于 Web 容器期望交付的应用程序的结构有一个严格的标准。而且该结构往往也会稍微反映到源布局中。这是一个页面,详细介绍了 Java 项目的一般项目结构(它们与我上面写的不太一致),特别是 J2EE 项目:

http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html

http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html

Maven projects

Maven项目

Mavenis a very versatile project build tool. Personally, my build needs are nicely met by ant, which roughly compares with nmake. Maven, on the other hand, is complete-lifecyle build management with dependency management bolted on. The libs and source for most of the code in the Java world is freely available in the 'net, and maven, if asked nicely, will go crawling it for you and bring home everything your project needs without you needing to even tell it to. It manages a little repository for you, too.

Maven是一个非常通用的项目构建工具。就个人而言,我的构建需求很好地满足了ant,大致与nmake. 另一方面,Maven 是完整的生命周期构建管理,带有依赖管理。Java 世界中大部分代码的库和源代码都可以在 'net 上免费获得,如果问得好,maven 会为您抓取它并将您的项目需要的一切带回家,而您甚至不需要告诉它。它也为您管理一个小存储库。

The downside to this highly industrious critter is the fact that it's highly fascist about project structure. You do it the Maven way or not at all. By forcing its standard down your throat, Maven manages to make projects worldwide a bit more similar in structure, easier to manage and easier to build automatically with a minimum of input.

这种高度勤奋的小动物的缺点是它对项目结构高度法西斯主义。你以 Maven 的方式做,或者根本不做。通过强制执行其标准,Maven 设法使世界范围内的项目在结构上更加相似,更易于管理,并且更容易以最少的输入自动构建。

Should you ever opt for Maven, you can stop worrying about project structure, because there can only be one. This is it: http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html

如果您曾经选择 Maven,您就不必担心项目结构,因为只有一个。就是这样:http: //maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html

回答by cletus

A package is much like a .Net namespace. The general convention in Java is to use your reversed domain name as a package prefix so if your company is example.com your packages will probably be:

包很像 .Net 命名空间。Java 中的一般约定是使用您的反向域名作为包前缀,因此如果您的公司是 example.com,您的包可能是:

com.example.projectname.etc...

It can be broken down to many levels rather than just one (projectname) but usually one is sufficient.

它可以分解为多个级别,而不仅仅是一个(项目名称),但通常一个就足够了。

Inside your project structure classes are usually divided into logical areas: controllers, models, views, etc. It depends on the type of project.

在您的项目结构中,类通常分为逻辑区域:控制器、模型、视图等。这取决于项目的类型。

There are two dominant build systems in Java: Ant and Maven.

Java 中有两个主要的构建系统:Ant 和 Maven。

Ant is basically a domain-specific scripting language and quite flexible but you end up writing a lot of boilerplate stuff yourself (build, deploy, test, etc tasks). It's quick and convenient though.

Ant 基本上是一种特定于领域的脚本语言,非常灵活,但您最终自己编写了很多样板内容(构建、部署、测试等任务)。不过它又快又方便。

Maven is more modern and more complete and is worth using (imho). Maven is different to Ant in that Maven declares that this project is a "Web application project" (called an archetype). Once that is declared the directory structure is mandated once you specify your groupId (com.example) and artifactId (project name).

Maven 更现代、更完整,值得使用(恕我直言)。Maven 与 Ant 的不同之处在于 Maven 声明该项目是“Web 应用程序项目”(称为原型)。声明后,一旦指定 groupId(com.example)和 artifactId(项目名称),就会强制要求目录结构。

You get a lot of stuff for free this way. The real bonus of Maven is that it manages your project dependencies for you so with a pom.xml (Maven project file) and correctly configured Maven you can give that to someone else (with your source code) and they can build, deploy, test and run your project with libraries being downloaded automatically.

您可以通过这种方式免费获得很多东西。Maven 的真正好处是它为您管理您的项目依赖项,因此使用 pom.xml(Maven 项目文件)和正确配置的 Maven 您可以将其提供给其他人(使用您的源代码),他们可以构建、部署、测试并使用自动下载的库运行您的项目。

Ant gets something like this with Ivy.

Ant 通过 Ivy 得到了类似的东西。

回答by danben

From Wikipedia:

来自维基百科:

A Java package is a mechanism for organizing Java classes into namespaces

Java 包是一种将 Java 类组织到命名空间中的机制

and

Java packages can be stored in compressed files called JAR files

Java 包可以存储在称为 JAR 文件的压缩文件中

So for package a.b.c, you could have Java classes in the a, a.b, and a.b.c packages. Generally you group classes inside the same package when they represent related functionality. Functionally, the only difference between classes in the same package and classes in different package is that the default access level for members in Java is "package-protected", which means that other classes in the same package have access.

因此,对于包 abc,您可以在 a、ab 和 abc 包中包含 Java 类。通常,当类表示相关功能时,您将它们分组到同一个包中。在功能上,同包中的类和不同包中的类的唯一区别是Java中成员的默认访问级别是“包保护”,这意味着同一包中的其他类都可以访问。

For a class a.b.c.MyClass, if you want to use MyClass in your project you would import a.b.c.MyClassor, less recommended, import a.b.c.*Also, for MyClass to reside in package a.b.c in the first place, you would declare it in the first line of MyClass.java: package a.b.c;.

对于一类abcMyClass,如果你想使用MyClass的在你的项目,你会import a.b.c.MyClass或不太推荐,import a.b.c.*另外,MyClass的居住在美国广播公司包摆在首位,你会在MyClass.java的第一行声明它:package a.b.c;

To do this you could JAR up the whole package (including packages b and c and class MyClass) and put this JAR into your $CLASSPATH; this would make it accessible for your other source code to use (via the aforementioned import statement).

为此,您可以 JAR 整个包(包括包 b 和 c 以及类 MyClass)并将此 JAR 放入您的$CLASSPATH; 这将使您的其他源代码可以使用(通过上述导入语句)。

回答by Nathan Hughes

A package is a grouping of source files that lets them see each others' package-private methods and variables, so that that group of classes can access things in each other that other classes can't.

包是一组源文件,它们可以让它们看到彼此的包私有方法和变量,以便该组类可以相互访问其他类不能访问的内容。

The expectation is that all java classes have a package that is used to disambiguate them. So if you open a jar file in your project, like spring, every package starts with org.springframework. The classloaders don't know about the jarfile name, they use only the package.

期望所有 java 类都有一个用于消除歧义的包。所以如果你在你的项目中打开一个 jar 文件,比如 spring,每个包都以 org.springframework 开头。类加载器不知道 jarfile 名称,它们只使用包。

There's a common practice of breaking things down by type of object or function, not everybody agrees about this. Like Cletus posted here, there's a tendency to group web controllers, domain objects, services, and data access objects into their own packages. I think some Domain-Driven Design people do not think this is a good thing. It does have the advantage that typically everything in your package shares the same kind of dependencies (controllers might depend on services and domain objects, services depend on domain objects and data access objects, etc.) so that can be convenient.

按对象或功能的类型分解事物是一种常见的做法,但并非所有人都同意这一点。就像这里发布的 Cletus 一样,人们倾向于将 Web 控制器、域对象、服务和数据访问对象分组到它们自己的包中。我认为一些领域驱动设计的人不认为这是一件好事。它的优点是通常包中的所有内容都共享相同类型的依赖项(控制器可能依赖于服务和域对象,服务依赖于域对象和数据访问对象等),因此很方便。

回答by Chad Okere

Okay so in java you have three different types of accessto a classes member functions and variables

好的,所以在 Java 中,您可以访问类成员函数和变量的三种不同类型

public protected package-privateand private

公共保护 包-私有和私有

All classes in the same package can see each others public, protected, and package-private elements.

同一个包中的所有类都可以看到彼此的 public、protected 和 package-private 元素。

Packages are not hierarchical in the system. Usually they are organized in a hierarchical way, but as far as runtime is concerned com.example.widgets is a completely different package from com.example.widgets.cogs

包在系统中不是分层的。通常它们以分层方式组织,但就运行时而言,com.example.widgets 是一个与 com.example.widgets.cogs 完全不同的包

Packages are arranged as directories, which helps keep things organized: your file structure is always similar to your package structure.

包按目录排列,这有助于使事情井井有条:您的文件结构始终与包结构相似。

They are planning on adding a module system to Java in JDK7 (called Project Jigsaw) and there is an existing module system called OSGi. These module systems will/can give you a lot more flexibility and power then the simple package system.

他们计划在 JDK7 中向 Java 添加一个模块系统(称为Project Jigsaw),并且有一个名为OSGi的现有模块系统。与简单的封装系统相比,这些模块系统将/可以为您提供更多的灵活性和功能。

Also, package names are usually all lower case. :)

此外,包名通常都是小写的。:)

回答by Jamie McCrindle

Here are some notes about Java packages that should get you started:

以下是一些有关 Java 包的注意事项,可以帮助您入门:

The best practice with Java package names is to use the domain name of the organisation as the start of the package, but in reverse, e.g. if your company owns the domain "bobswidgets.com", you would start your package off with "com.bobswidgets".

Java 包名称的最佳实践是使用组织的域名作为包的开头,但反过来,例如,如果您的公司拥有域“bobswidgets.com”,则您的包将以“com”开头。小工具”。

The next level down will often be the application or library level, so if it's your ecommerce libraries, it could be something like "com.bobswidgets.ecommerce".

下一个级别通常是应用程序或库级别,因此如果是您的电子商务库,它可能类似于“com.bobswidgets.ecommerce”。

Further down than that often represents the architecture of your application. Classes and interfaces that are core to the project reside in the "root" e.g. com.bobswidgets.ecommerce.InvalidRequestException.

比这更深的通常代表您的应用程序的架构。作为项目核心的类和接口驻留在“根”中,例如 com.bobswidgets.ecommerce.InvalidRequestException。

Using packages to subdivide functionality further is common. usually the pattern is to put interfaces and exceptions into whatever the root of the subdivision is and the implementation into sub packages e.g.

使用包来进一步细分功能是很常见的。通常模式是将接口和异常放入细分的根所在的任何内容中,并将实现放入子包中,例如

com.bobswidgets.ecommerce.payment.PaymentAuthoriser (interface)
com.bobswidgets.ecommerce.payment.PaymentException
com.bobswidgets.ecommerce.payment.paypal.PaypalPaymentAuthoriser (implementation)

This makes it pretty easy to pull the "payment" classes and packages into their own project.

这使得将“支付”类和包拉入他们自己的项目变得非常容易。

Some other notes:

其他一些注意事项:

Java packages are tightly coupled to directory structure. So, within a project, a class with a Package of com.example.MyClass will invariably be in com/example/MyClass.java. This is because when it is packaged up into a Jar, the class file will definitely be in com/example/MyClass.class.

Java 包与目录结构紧密耦合。因此,在项目中,包含 com.example.MyClass 包的类将始终位于 com/example/MyClass.java 中。这是因为打包成Jar后,class文件肯定在com/example/MyClass.class。

Java packages are loosely coupled to projects. It is quite common that projects will have their own distinct package names e.g. com.bobswidgets.ecommerce for ecommerce, com.bobswidgets.intranet for the intranet project.

Java 包与项目松散耦合。项目有自己独特的包名称是很常见的,例如 com.bobswidgets.ecommerce 代表电子商务,com.bobswidgets.intranet 代表内部网项目。

Jar files will container the class files that are the result of compiling your .java code into bytecodes. They are just zip files with .jar extension. The root of the Jar file is the root of the namespace hierarchy e.g. com.bobswidgets.ecommerce will be /com/bobswidgets/ecommerce/ in the Jar file. Jar files can also container resources e.g. property files etc.

Jar 文件将包含类文件,这些文件是将 .java 代码编译为字节码的结果。它们只是带有 .jar 扩展名的 zip 文件。Jar 文件的根是命名空间层次结构的根,例如 com.bobswidgets.ecommerce 在 Jar 文件中将是 /com/bobswidgets/ecommerce/。Jar 文件还可以包含资源,例如属性文件等。

回答by dball917

A package in Java is very similar to a namespace in .Net. The name of the package essentially creates a path to the classes that live inside it. This path can be thought of as the class's namespace (in .Net terms) because it is the unique identifier for the specific class you want to use. For example if you have a package named:

Java 中的包与 .Net 中的命名空间非常相似。包的名称本质上创建了一个指向位于其中的类的路径。这个路径可以被认为是类的命名空间(在 .Net 术语中),因为它是您要使用的特定类的唯一标识符。例如,如果您有一个名为的包:

org.myapp.myProject

And inside it you had a bunch of classes:

在它里面你有一堆类:

MyClass1
MyClass2

To specifically refer to those classes you would use:

要专门引用您将使用的那些类:

org.myapp.myProject.MyClass1
org.myapp.myProject.MyClass2

The only real difference between this and .Net (that I know of) is that Java organizes its "namespaces" structurally (each package is a distinct folder) whereas .Net allows you to scope classes using the namespacekeyword and ignores where the document actually lives.

这与 .Net(我所知道的)之间唯一真正的区别是 Java 在结构上组织其“命名空间”(每个包都是一个不同的文件夹),而 .Net 允许您使用namespace关键字来限定类的范围并忽略文档实际所在的位置.

A JAR file is roughly analogous to a DLL in most cases. It is a compressed file (you can open them with 7zip) that contains source code from other projects that can be added as dependencies in your application. Libraries are generally contained in JARs.

在大多数情况下,JAR 文件大致类似于 DLL。它是一个压缩文件(您可以使用 7zip 打开它们),其中包含来自其他项目的源代码,这些源代码可以作为依赖项添加到您的应用程序中。库通常包含在 JAR 中。

The thing to remember about Java is that is is very structural; WHERE files live is important. Of course there is more to the story then what I posted but I think this should get you started.

关于 Java 需要记住的是它是非常结构化的;WHERE 文件的位置很重要。当然,故事比我发布的内容更多,但我认为这应该让你开始。

回答by Carl Smotricz

To answer the example sub-question:

要回答示例子问题:

package com.smotricz.goodfornaught;

import java.util.HashMap;
import javax.swing.*;

public class MyFrame extends JFrame {

   private HashMap myMap = new HashMap();

   public MyFrame() {
      setTitle("My very own frame");
   }

}

回答by Tobias N. Sasse

Do .JAR files contain compiled code? Or just compressed source code files?

.JAR 文件是否包含已编译的代码?或者只是压缩的源代码文件?

They might contain both, or even totally different kinds of files like pictures. It's a zip archive first of all. Most often you would see JARs that contain class files, and those which contain source files (handy for debugging in your IDE if you use third party code) or those that contain javadoc (sourcecode documentatin), also handy if your IDE supports tooltipping the documentation when you access the lib's functions.

它们可能包含两者,甚至完全不同类型的文件,如图片。它首先是一个 zip 存档。大多数情况下,您会看到包含类文件的 JAR 和包含源文件的 JAR(如果您使用第三方代码,则可以方便地在 IDE 中进行调试)或包含 javadoc(源代码文档)的 JAR,如果您的 IDE 支持工具提示文档,则也很方便当您访问 lib 的函数时。

Is there a good reason why package names are all lower case?

包名全部小写是否有充分的理由?

Yes there is a good reason for package names to be written in lowercase letters: There is a guideline which says that only classnames are written with a capital letter in front.

是的,包名用小写字母写有一个很好的理由:有一个指导方针说只有类名前面写有大写字母。

Can Packages have 'circular dependencies'? In other words, can Package.A use Package.B and vice versa?

包可以有“循环依赖”吗?换句话说,Package.A 可以使用 Package.B,反之亦然吗?

Packages do not use each other. Only classes do. And yes that might be possible but bad practice.

包不相互使用。只有课堂可以。是的,这可能是可能的,但不好的做法。

Can anyone just show the typical syntax for declaring a class as being in a package and declaring that you wish to reference another package in a class (a using statement maybe?)

任何人都可以展示用于将类声明为在包中并声明您希望引用类中的另一个包的典型语法(可能是 using 语句?)

Let's assume you want to use the ArrayList class from package java.util, either use

假设您要使用包 java.util 中的 ArrayList 类,要么使用

 import java.util.ArrayList;
 ArrayList myList = new ArrayList(); 

or use without import (say you use two different classes named ArrayList from different packages)

或不使用导入(假设您使用来自不同包的两个名为 ArrayList 的不同类)

 java.util.ArrayList myList = new java.util.ArrayList();
 your.package.ArrayList mySecondList = new your.package.ArrayList();

回答by Jerry Brandenberger

While it is not as easy to make circular dependent classes work, it may not be impossible. I did get it to work in one case. class A and class B depended on each other and wouldn't compile from scratch. but realizing that a part of class A didn't need class B, and that part was what class B needed to compile completely, I rem'd out that part of class A, not needed by class B, and the remaining part of class A was able to compile, then I was able to compile class B. I was then able to un-rem that section of class A that needed class B, and was able to compile the full class A. Both classes then functioned properly. While it is not typical, if the classes are tied together like this, it is kosher and at times possibly necessary. Just make sure you leave yourself special compile instructions for future updates.

虽然使循环依赖类工作并不那么容易,但并非不可能。我确实让它在一种情况下工作。A 类和 B 类相互依赖,不会从头开始编译。但是意识到 A 类的一部分不需要 B 类,而那部分是 B 类需要完全编译的部分,我重新列出了 A 类的那部分,B 类不需要,以及类的其余部分A 能够编译,然后我能够编译 B 类。然后我能够解除 A 类需要 B 类的部分,并且能够编译完整的 A 类。然后两个类都正常运行。虽然这不是典型的,但如果这些类像这样联系在一起,它是洁净的,有时可能是必要的。只需确保为自己留下特殊的编译说明以备将来更新。