《JAVA程序设计》期末考试试题
《JAVA程序设计》期末考试试题
在Java语言中,下列哪个变量名是不正确的 ( )
(A) large (B) 2much
(C) $money (D) _postCode
关于抽象类下列哪个描述正确? ( )
抽象类不能包含抽象方法。
接口和抽象类是一回事。
抽象类不能实例化,即不能生成对象。
抽象类可以实例化对象。
3. 以下对封装的描述正确的是( )
(A) 只能对一个类中的方法进行封装,不能对属性性进行封装 (B) 如果子类继承了父类,对于父类中进行封装的方法,子类仍然可以直接调用 (C) 封装的意义不大,因此在编码时尽量不要使用 (D) 封装的主要作用在于对外隐藏内部实现细节,增强程序的安全性
4. 下面关于Applet的说法正确的是: ( )
Applet也需要main方法
Applet必须继承java.awt.Applet
Applet能访问本地文件
Applet程序不需要编译
5.以下对继承的描述错误的是( )
(A) Java中子类只能继承单个父类。 (B) Java中子接口只能继承单个接口。 (C) Java中子类可以实现多个接口。 (D) 当实例化子类时会先实例化父类。
6.在使用super 和this关键字时,以下描述正确的是( ) (A) 在子类构造方法中使用super()显示调用父类的构造方法,super()必须写在子类构造方法的第一行,否则编译不通过 (B) super()和this()不一定要放在构造方法内第一行 (C) this()和super()可以同时出现在一个构造函数中 (D) this()和super()可以在static环境中使用,包括static方法和static语句块
7. 如果有一个对象myListener, 为了使myListener对象能够接受并处理来自于smallButton按钮对象的点击动作事件,myListener对象应该实现哪个接口? ( )
(A)ActionListener
(B)ItemListener
(C)MouseListener
(D)WindowListener
8. 下列情况中,不会使线程返回所持有的对象锁的是( )
(A) 当synchronized()语句块执行完毕
(B) 当调用了线程的suspend()方法 (C) 当在synchronized()语句块中出现异常(exception)
(D) 当持有锁的线程调用该对象的wait()方法
9.下列代码执行结果是什么? ( )
String s1 = \”ccc\”;
s1.concat(\”fff\”);
System.out.println(s1);
The string \”ccc\”.
The string \”cccfff\”.
The string \”fff\”.
The string \”fffccc\”
10. 当变量x是哪些值的时候输出包括\”Message 2\”,选出最完整的答案? ( )
switch(x)
{ case 1 :
System.out.println(\”Message 1\”);
case 2 :
case 3 :
System.out.println(\”Message 2\”);
case 4 :
System.out.println(\”End\”);
}
(A) 3 (B) 1 或 2 或 3 或 4
(C) 1 或 2 或 3 (D) 4
1.请简述String和StringBuffer的联系和区别。
2.请简述抽象类和接口的区别。
1. 请写出以下程序的输出结果。
public class Demo{
public static void main(String[] args) {
Integer a = new Integer(1);
Integer b = new Integer(2);
if(a==b)
System.out.println(“true”);
else
System.out.println(“false”);
}
}
2. 下面的代码执行结果是什么?
public class TestThis{
private int i=0;
TestThis increment(){
i++;
return this;
}
void print(){
System.out.println(i);
}
public static void main(String[] args){
TestThis x = new TestThis();
x.increment().increment().increment().print();
}
}
3.下列程序输出什么?
class J {
static void swap(String s0, String s1) {
String s = s0;
s0 = s1;
s1 = s;
}
public static void main(String args[]) {
String[] s = { \”1\”, \”2\” };
swap(s[0], s[1]);
System.out.println(s[0] + s[1]);
}
}
4. 读程序,写出正确的运行结果。
public class test {
static int m = 9;
public static void main(String[] args) {
test fd1 = new test();
fd1.m++;
test fd2 = new test();
System.out.println(fd1.m + “,” + fd2.m);
}
}
5. 阅读下列代码,写出运行结果。
public class Demo {
public static void main(String[] args) {
int i = 12;
System.out.println(i += i -= i *= i);
}
}
6. 阅读以下程序,写出运行结果。 class Q1{ public static void main(String args[ ]){ double d=1.23; Dec dec=new Dec( ); dec.decrement(d); System.out.println(d); } classs Dec{ public void decrement(double decMe){ decMe = decMe - 0.1; } }
四. 阅读程序,回答问题。(20分)
如果有这样一个Java源文件如下,阅读程序,回答下面几个问题:
public class Shelf{
public static void main(String[] arguments) {
System.out.println(\”Shelf!\”);
Book b = new Book();
b.get();
}
}
class Book {
public void get() {
System.out.println(\” book!\”);
}
}
class Student {
public void read() {
System.out.println (\”read a book!\”);
}
}
(1) 请写出这个文件的完整名称(3分)
(2) 请写出在命令行上如何编译这个文件(3分)
(3) 请写出这个文件编译后产生几个类文件(2分),它们的完整名称分别是什么?(6分)
(4) 请写出在命令行上如何运行这个程序?(2分)
(5) 这个程序的运行结果是什么?(4分)
Java程序设计试卷
JAVA程序设计试卷库(第5套)
一、单选题(每小题 2 分,共 20 分)
1、Java Application源程序的主类是指包含有( A )方法的类。
A. main方法 B. toString方法
C. init方法 D. actionPerfromed方法
2、分析下面的程序段,下面的哪个描述是正确的。( B )
char mychar=’c’;
switch(mychar){
default:
case ‘a’: System.out.println(“a”);break;
case ‘b’: System.out.println(“b”);break;
}
A. switch语句块是错误的,因为switch后面的表达式值的类型不是整数;
B. switch语句块是正确的;
C. switch语句块是错误的,因为default没有放在语句块的最后面;
D. 代码运行时,没有任何输出结果。
3、编译并运行下面的Java程序,将产生( B )结果。
class A{
int var1=1;
int var2;
public static void main(String[] args){
int var3=3;
A a=new A();
System.out.println(a.var1+a.var2+var3);
}
}
A. 0 B. 4
C. 3 D. 代码无法编译,因为var2根本没有被初始化
4、在Java中,下面关于包的陈述中正确的是( D )。
A. 包的声明必须是源文件的任意位置;
B. 包的声明必须紧跟在import语句的后面;
C. 只有公共类才能放在包中;
D. 可以将多个源文件中的类放在同一个包中
5、 在Java语言中,当一个类的某个变量声明为protected时下列说法正确的是( C )。
A. 只有同一类中的成员才能访问它;
B. 不同包中的任何其他类都能够访问它;
C. 同包中的任何其他类能够访问它;
D. 不同包中的子类不可以访问该变量。
6、在Java中,执行下面的语句后,c的值为( D )。
String s= \”Jessica \”;
char c=s.charAt(6);
A. \”c \” B. \”a \”
C. \’c \’ D. \’a \’
7、设有下面两个赋值语句:
a = Integer.parseInt(“1024”);
b = Integer.valueOf(“1024”).intValue();
下述说法正确的是( D )。
A.a是整数类型变量,b是整数类对象。
B.a是整数类对象,b是整数类型变量。
C.a和b都是整数类对象并且它们的值相等。
D.a和b都是整数类型变量并且它们的值相等。
8、事件剪裁类如WindowAdapter(它实现了WindowListener接口)的优点是什么? ( C )。
A. 继承了那个类的所有行为 ;
B. 子类自动成为监听器;
C. 没有必要实现不使用的任何WindowListener接口中定义的方法;
D.可以自动充当事件的监听者。
9、在用Java构建动画时,(C )方法创建新线程并启动它运行。
A. init() B. start()
C. run() D. paint()
10、下面哪一个选项能正确地创建一个InputStreamReader对象( A )。
A.new InputStreamReader(new FileInputStream(“data”))
B.new InputStreamReader(new FileReader(“data”))
C.new InputStreamReader(new BufferedReader(“data”))
D.new InputStreamReader(“data”)
二、填空题(每空格1分,共15分)
1、阅读下面的程序片段,在①中,parent类与child类之间是继承关系;在②中,parent类与child类之间包含。
① class parent{
int fields;
}
class child extends parent{
int fieldChild;
}
② class child{
int fieldsChild;
}
class parent {
child myChild;
}
2、Java中的多态有两种方式:子类对父类方法的覆盖、同类中方法的重载。
3、下面程的输出结果是:?吗对,上海自来水来自海上
public class turnString {
public static void main(String args[]) {
String s=“上海自来水来自海上,对吗?” ;
for(int i=s.length( )-1;i>=0;i++)
System.out.println(s.charAt(i));
System.out.println():
}
}
4、Applet的init( )方法仅在开始时执行一次?start( )方法在用户每次访问包含Applet的HTML文件时都被调用?
5、创建一个FlowLayout的对象fd,使应用该布局管理器的各个组件都向右对齐排列。该对象的创建语句为:FlowLayout fd=new FlowLayout(FlowLayout.RIGHT);。
6、java.net包中定义的两个类Socket、ServerSocket;分别用来实现双向连接的Client和Server端。
7、巳知a=14,b=3,则表达式a<<b运算结果为:112;。
8、写出运行下面程序片段后的屏幕输出:0 1 2 i=3。
int i;
for(i=0;i<5;i++)
{
if(i==3)
break;
System.out.print(i+” ”);
}
System.out.println(“i=”+i)
9、在Java Application程序中,一个类是主类的标志是包含main( )方法,在Java Applet程序中,一个类是主类的标志是该类是Applet类的子类;。
10、多态的概念是一个程序中同名的不同方法共存的情况。。
三、判断改错题(每题2分,共20分)(正确的打√,错误的打×并说明原因)
1、 Java系统包提供了很多预定义类,我们可以直接引用它们而不必从头开始编写程序。 (√ )
2、 程序可以用字符‘*’替代一个TextField中的每个字符的显示,使别人看不出其中的具体内容。( √)
3、 Class1类的属性被private修饰符修饰为私有变量,所以方法不能访问它。(×,Class1类自身的方法可以访问这个私有变量。 )
4、 如果p是父类Parent的对象,而c是子类Child的对象,则语句c=p是正确的。(×,如果p实际代表的是一个子类对象的引用,可以用强制类型转换成c=(Child)p;否则不能把父类对象赋值给子类对象。 )
5、 如果希望程序能够处理所有的异常,包括未知的异常,可以在所有的catch块后面加下catch(Exception e){}。(√ )
6、 TextComponent是一个抽象类,它的两个子类TextField和TextArea才拥有具体的对象。( √)
7、 一个Applet程序在运行过程中,创建的Frame窗框,当Applet或浏览器关闭时也会自动跟着关闭。(×,Frame与Applet平级,不受Applet的关闭的影响。 )
8、 判断下面程序片段的正确性。(×,Vector对象的addElement( )方法的参数类型为对象,所以myv.addElement(i)应改为所以myv.addElement(new Integer(i)); )
import java.util.*;
public class UseVector{
public static void main(String args[])
{
Vector myv=new Vector( );
for(int i=0;i<10;i++)
myv.addElement(i);
}
}
9、 在Applet中显示一幅图像,首先要把它调入内存,保存在一个Image对象中,然后调用drawImage()方法画出这个图像。(√)
10、挂起、阻塞或等待的线程都能够恢复运行,但是停止运行的线程将不可能再运行(√)。
四、问答题(每小题10分,共30分)
1、 阅读下面的程序片段,并回答问题。
① Class1被称为是Class2的什么?Class2被称为是Class1的什么?
② Class1有哪些属性和方法?Class2有哪些属性和方法?其中哪些与Class1的属性和方法有关?
class Class1
{
int field1;
private int field2;
void method1( )
{
System.out.println(“我是Class1的第一个方法”);
}
void method2( )
{
System.out.println(“我是Class1的第二个方法”);
}
}
class Class2 extends Class1{
int fieldChild1;
void methodchild1()
{
System.out.println(“我是Class2的第一个方法”);
}
}
1、 阅读下面的程序片段,并回答问题。
① Class1被称为是Class2的什么?Class2被称为是Class1的什么?
答:Class1被称为Class2的父类,Class2被称为是Class1的子类。
② Class1有哪些属性和方法?Class2有哪些属性和方法?其中哪些与Class1的属性和方法有关?
答:Class1包括属性field1和field2,方法method1和method2;Class2包括自身定义的属性fieldChild1和自身定义的方法methodChild1,以及它从父类继承来的属性field1和方法method1、method2。
2、写出下面程序的功能
import java.applet.Applet;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class DataType extends Applet implements ActionListener
{ Label prompt=new Label(\”请分别输入整数和浮点数:\”);
TextField input_int=new TextField(6);
TextField input_double=new TextField(6);
TextField output=new TextField(35);
int getInt; double getDouble;
public void init() {
add(prompt); add(input_int); add(input_double);
add(output); output.setEditable(false); input_double.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
getInt=Integer.parseInt(input_int.getText());
getDouble=Double.parseDouble(input_double.getText());
output.setText(\”您输入了整数: \”+getInt+\”和浮点数:
\”+getDouble);
}
}
2、写出下列程序完成的功能
答:功能:从图形界面输入一个整数和一个浮点数,然后将其输出来。
3、 说明下面程序段是否有误,如有误,请将错误的地方指出来,并改正
Interface MyInterface
{
void method1();
}
abstract class Parent implements MyInterface
{ }
class Child extends Parend
{
void method1()
{
System.out.println(“I am implemented now!”);
}
}
3、说明下面程序是否有误,如有误,请将错误的地方指出来,并改正
答:接口中的方法都是public ,所以重载方法也必须声明为public.
class Child extends Parend
{
{
System.out.println(“I am implemented now!”);
}
}
五、用Java语言编写程序。(共15分)
假设用户输入一组整数被保存在Vector对象中,请定义一个类vecSort,用来求Vector对象中整数中的最大和最小数据。
要求:
1、 根据题目给出vecSort类应包含的属性和方法(5分)
2、 用Java语言定义类vecSort(10分)
五、用Java语言编写程序。(共15分)
参考代码:
class vecSort{
int max,min;
Vector x=new Vector();
vecSort(Vector y)
{
for(int i=0;i<y.size() ;i++)
x.addElement(y.elementAt(i) );
}
int getmax()
{ max=((Integer)(x.elementAt(0))).intValue() ;
for(int i=1;i<x.size();i++)
if(max<((Integer)(x.elementAt(i))).intValue())
max=((Integer)(x.elementAt(i))).intValue();
return max;
}
int getmin()
{ min=((Integer)(x.elementAt(0))).intValue() ;
for(int i=1;i<x.size();i++)
if(min>((Integer)(x.elementAt(i))).intValue())
min=((Integer)(x.elementAt(i))).intValue();
return min;
}
}
Java9模块化出来这么久了,你了解过没(入门使用指南)
Java9在包之上引入了一个新的抽象级别,正式名称为 Java 平台模块系统(JavaPlatform Module System,JPMS) ,简称模块。
接下来,这篇文章将会介绍模块化的基本概念,同时我还将构建一个简单的项目来演示我们将在本指南中学习的所有概念。
首先,为了更好的去使用模块之前,我们需要去了解什么是模块。
模块是一组紧密相关的包和资源同时伴随一个模块描述符文件。
换句话说,可以简单抽象为它是Java包上的包,以便允许我们的代码能够更加的被复用。
模块中的包与我们自 Java 诞生以来一直在使用的 Java 包完全相同。
当我们创建一个模块时,我们在内部组织包中的代码,就像我们以前对任何其他项目所做的那样。
除了组织我们的代码之外,还使用包来确定哪些代码可以在模块之外公开访问。我们将在本文后面花更多时间讨论这个问题。
每个模块都需要负责和管理其资源文件,比如:媒体资源或者配置文件。
以前,我们将所有资源放在项目的根级别,并手动管理哪些资源属于应用程序的不同部分。
使用模块,我们可以将所需的图像和 XML 文件与所需的模块一起发布,从而使我们的项目更容易管理。
当我们创建一个模块时,我们包含了一个描述符文件,它从以下几个方面定义了一个新模块:
- 名称(Name) – 模块名称
- 依赖(Dependencies) – 该模块所依赖的其他模块的列表
- 公有包(public Packages)– 我们希望从模块外部访问的所有包的列表
- 服务提供(Services Offered)– 我们可以提供其它模块可以使用的服务实现
- 服务消费(Services Consumed)– 允许当前模块成为服务的使用者
- 反射权限(Reflection Permissions)– 显式地允许其他类使用反射来访问包的私有成员
模块命名规则类似于我们如何命名包(允许用点,但是不允许用破折号)。一般常用的就是项目式风格(my.module)或者域名反转(com.demo.mymodule)风格。
我们需要列出所有希望公开的包,因为默认情况下所有包都是模块私有的。
反射也是如此。默认情况下,我们不能对从另一个模块导入的类使用反射。
在本文的后面,我们将看到如何使用模块描述符文件的示例。
在新的模块系统中有四种类型的模块:
- 系统模块(System Modules)– 这些可以通过 list-module 命令列出所有的系统模块,它们包含Java SE和JDK模块。
- 应用模块(Application Modules)– 当我们决定使用模块时,通常需要构建这些模块。它们在组装的 JAR 中,并且命名和定义在已编译的module-info.class中。
- 自动模块(Automatic Modules)– 我们可以通过将现有的 JAR 文件添加到模块路径来包含非官方模块。模块的名称将从 JAR 的名称派生(使用JAR名称)。自动模块将对路径加载的每个其他模块具有完全读访问权限。
- 未命名模块(Unnamed Module)– 当一个类或 JAR 被加载到类路径(而不是模块路径)时,它会自动添加到未命名的模块中。这是一个全面覆盖的模块,可以用以前编写的 Java 代码来维护向下兼容。
模块可以通过以下两种方式发布:作为一个 JAR 文件或作为一个编译的项目。
我们可以创建由一个“主应用程序”和几个库模块组成的多模块项目。
但是我们必须小心,因为每个 JAR 文件只能有一个模块。
在设置构建文件时,需要确保将项目中的每个模块绑定为一个单独的 jar。
当我们安装了Java 9,我们会看到JDK会有一个全新的结构。
他们已经把所有原来的软件包都搬到了新的模块系统中。
通过在命令行中键入内容,我们可以看到这些模块是什么:
这些模块分为四个主要组: java、 javafx、 jdk 和 Oracle。
Java 模块是核心 SE 语言规范的实现类。
Javafx 模块是 FX UI 库。
JDK 本身需要的任何东西都保存在 JDK 模块中。
最后,任何特定于 Oracle 的东西都在 Oracle 模块中。
要设置一个模块,我们需要在包的根目录下放置一个特殊的文件 – module-info.java。
该文件称为模块描述符,包含构建和使用新模块所需的所有数据。
我们用一个声明来构造这个模块,这个声明的主体要么是空的,要么是由模块指令组成的:
我们使用 module 关键字开始模块声明,然后使用模块名称跟随声明。该模块将使用此声明,但是我们通常需要更多信息。这就是模块指令的用武之地。
我们的第一个指令是requires。这个模块指令允许我们声明模块依赖项:
现在,my.module 对 module.name 既有运行时依赖关系,也有编译时依赖关系。
当我们使用此指令时,我们的模块可以访问从依赖项导出的所有公共类型。
有时我们编写的代码引用另一个模块,但是我们库的用户永远不会想要使用这些代码。
例如,我们可能会写一个格式化打印内部状态的工具,同时此刻已经包含一个存在的日志模块。但是,不是所有使用我们库的用户都想要这个工具,并且他们也不想包含额外的日志库。
在这些情况下,我们希望使用一个可选的依赖项。通过使用requires static指令,我们创建了一个仅编译时的依赖项:
通常为了方便处理这些模块库,我们需要这些库具有传递性。
但是,我们需要确保引入我们代码的任何模块也将引入这些额外的“传递”依赖项,否则它们将无法工作。
幸运的是,我们可以使用requires transitive指令来强制任何下游消费者也能使用我们所需的依赖项:
现在,当一个开发人员需要 my.module 时,他们不必说还需要 module.name 才能让我们的模块继续工作。
默认情况下,模块不向其他模块公开任何 API。这种强封装是最初创建模块系统的关键原因之一。
我们的代码明显更加安全,但是现在我们需要显式地向外界开放我们的 API,如果我们希望它可用的话。
我们使用 export 指令暴露所有的公共成员:
现在,当有人需要 my.module 时,他们可以访问我们的 com.my.package.name 包中的 public 类型,但不能访问其他任何包。
我们可以使用exports…to来开放我们的公共类给所有访问模块。
但是,如果我不想让所有模块都能访问我们的api怎么办?
我们可以使用 export… to 指令限制哪些模块可以访问我们的 API。
类似exports指令,我们声明了一个可以导出的包。但是,我们同时列出了哪些模块是可以通过requires指令来导入这些包的。
一个服务是其他类可以使用的特定接口或抽象类的实现。
我们使用 uses 指令指定模块使用的服务。
注意,我们使用的类名是服务的接口或抽象类,而不是实现类:
在这里我们应该注意到,在需求指令和使用指令之间有一个区别。
我们可能需要一个模块,该模块提供我们想要使用的服务,但该服务实现了来自其传递依赖关系之一的接口。
为了以防万一,我们不强制模块需要所有的传递依赖项,而是使用 uses 指令将所需的接口添加到模块路径中。
模块也可以是其他模块可以使用的服务提供者。
指令的第一部分是 provides关键字,这里便是我们放置接口或抽象类名的地方。
接下来,我们有 with 指令,这里提供实现接口或扩展抽象类的实现类名。
我们前面提到过封装是设计这个模块系统的驱动因素。
在Java9之前,可以使用反射来检查包中的每个类型和成员,甚至是私有类型。没有什么是真正封装的,这个会给库的开发人员带来各种各样的问题。
由于Java9的强制实行了强封装,我们现在必须显式地授予其他模块对我们的类进行反射的权限。
如果我们想继续像旧版 Java 那样允许完全反射,我们可以简单地打开整个模块:
如果我们需要允许私有类型的反射,但是我们不想暴露所有的代码,我们可以使用Opens指令去暴露指定的包。
但是请记住,这个将会开放这个包给整个外界,所以请确保这是你想要做的:
有时候反射确实能给我们带来很多便利性,但是我们仍然需要从封装中获得尽可能多的安全性。我们可以有选择地打开我们的包到一个预先批准的模块列表,在这种情况下,使用 open… to 指令:
到目前为止,对 Java9模块的支持已经添加到 Maven 和 Gradle 中,因此您不需要对项目进行大量的手工构建。但是,了解如何从命令行使用模块系统仍然很有价值。
我们将在下面的完整示例中使用命令行来帮助巩固整个系统在我们头脑中的工作方式。
- module-path – 我们使用-module-path选项来指定模块路径,这是包含你的模块的一个或多个目录的列表。
- add-reads – 我们可以通过使用命令行-add-reads来等效代替描述文件中的requires指令。
- add-exports – 代替exports指令
- add-opens – 代替open指令
- add-modules – 将模块列表添加到默认的模块集中
- list-modules – 打印所有模块及其版本字符串的列表
- patch-module – 在模块中添加或重写类
- illegal-access=permit|warn|deny – 要么通过显示单个全局警告来放松强封装,要么显示每个警告,要么错误导致失败。默认情况下是允许的。
我们应该花一点时间来讨论代码的可见性。
许多库和框架都是通过反射来体现出其威力(比如:Junit和Spring)。
在 Java9中默认情况下,我们只能访问导出包中的公共类、方法和字段。即使我们使用反射去获取访问非公开的成员并设置setAccessible(true),我们也不能访问这些成员。
我们可以使用open,opens,和opens…to来为反射授予仅运行时访问,注意的是,仅运行时。
我们无法针对私有类型进行编译,而且无论如何也不需要这样做。
如果我们必须访问一个模块进行反射,而且我们不是该模块的所有者(例如,我们不能使用 open… to 指令) ,那么可以使用命令行-add-open 选项允许自己的模块在运行时对锁定的模块进行反射访问。
这里唯一需要注意的是,您需要访问命令行参数,这些参数用于运行模块以使其工作。
现在我们知道了模块是什么以及如何使用它们,让我们继续构建一个简单的项目来演示我们刚刚学到的所有概念。
为了简单起见,我们不会使用 Maven 或 Gradle。相反,我们将依靠命令行工具来构建我们的模块。
首先,我们需要设置我们的项目结构。我们将创建几个目录来组织我们的文件。
首先创建项目文件夹:
这是我们整个项目的基础,所以在这里添加文件,如 Maven 或 Gradle 构建文件,其他源目录和资源。
我们还放置了一个目录来保存所有特定于项目的模块。
接下来,我们创建一个模块目录:
下面是我们的项目结构:
现在我们已经有了基本的结构,让我们添加第一个模块。
在 simple-module 目录下,创建一个名为 hello.module 的新目录。
除了遵循包命名规则之外,我们可以给这个命名任何我们想要的东西。如果愿意,我们甚至可以使用主包的名称作为模块名称,但是通常,我们希望使用与创建此模块的 JAR 相同的名称。
在我们的新模块下,我们可以创建我们想要的包。在我们的示例中,我们将创建一个包结构:
接下来,在这个包中创建一个名为 HelloModules.java 的新类:
最后,在 hello.module 根目录中,添加我们的模块描述符; module-info. java:
为了使这个示例保持简单,我们所做的就是导出 com.demo.modules.hello 包的所有公共成员。
我们的第一个模块已经好了,但它什么都不做。
我们现在可以创建一个使用它的第二个模块。
在 simple-module 目录下,创建另一个名为 main.app 的模块目录。这次我们将从模块描述符开始:
我们不需要向外界透露任何信息。相反,我们所需要做的就是依赖于我们的第一个模块,因此我们可以访问它导出的公共类。
现在我们可以创建一个使用它的应用程序。
创建一个新的包结构:com.demo.modules.main。
接下来,创建一个新的类文件叫:MainApp.java。
这就是我们演示模块所需的全部代码。我们的下一步是从命令行构建并运行此代码。
要构建我们的项目,我们可以创建一个简单的 bash 脚本并将其放在项目的根目录下。
创建一个名为 compile-simple-modules.sh 的文件:
这个命令有两部分,javac 和 find 命令。
Find 命令只是在 simple-module 目录下输出所有. java 文件的列表。然后,我们可以将该列表直接提供给 Java 编译器。
与旧版 Java 不同的是,我们必须提供一个 module-source-path 参数来告诉编译器它正在构建模块。
运行此命令后,我们将拥有一个 outDir 文件夹,其中包含两个已编译的模块。
现在我们终于可以运行代码来验证模块是否正常工作了。
在项目的根目录中创建另一个文件: run-simple-module-app.sh。
要运行一个模块,我们必须至少提供模块路径和主类。如果一切正常,你应该看到:
在这篇文章中,我们重点介绍了新的 Java9模块系统的基础知识。我们开始讨论什么是模块。接下来,我们讨论了如何发现 JDK 中包含哪些模块。我们还详细介绍了模块声明文件。最后,我们根据前面的基础概念构建和运行了我们自己的简单的模块应用。到现在你应该对Java9的模块化有一定的了解了吧。
本文作者及来源:Renderbus瑞云渲染农场https://www.renderbus.com
文章为作者独立观点不代本网立场,未经允许不得转载。