在上一篇笔记中,我们进行简单的人机交互介绍时,引入了一个Scanner类,在所有使用到Scanner的类里,在最开始都有一段代码 import java.util.Scanner;在此之前,我们的代码第一段总是public class XXXX。如果我们去掉import java.util.Scanner;看看会发生什么情况
public class OfferServer{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int time = 0;
int sum = 0;
while(scan.hasNextInt()){
int i = scan.nextInt();
time++;
sum += i;
}
System.out.println("你输入了"+time+"个数,它们的和是"+sum);
}
}
编译的时候出错了,因为没有定义Scanner类,为什么出现这个问题?我们需要从java的组织结构说起。
我们知道java是一个庞大的编程语言,它有很多很多的代码,很多很多个类。我们不可能把成千上万个类都丢在一个文件夹里,那样你要找一个类修改一个方法一个属性,简直就是灾难。所以java引入了包的概念(package),把功能类似、或者为了同一个目的而创建的不同的类,以包的形式整合和区分。就如果我们的行政区划一样。如果没有省份的概念,没有地市县的概念,没有乡镇村的概念,只有国家的概念,那我们的生活会是什么样子?你买个快递要送到哪里?东经多少度北纬多少度吗?
所以在java里面出现包的概念后,很好的把代码组织分类起来。我们在前面介绍public、protected、default、private这些修饰符时,曾经介绍过,deafult是包内可访问的,protected是包内以及子类可访问的,包的出现也让权限控制更加灵活。另外,在不同的包下,我们还可以创建名字相同的类,而正是由于这一点,我们在对类进行引用时,要加上它的全部路径。一个累的全部路径,应该是它的包路径加上类名,比如我们引入的Scanner,它的路径就是java.util.Scanner。它是java包下面的util包中的Scanner类。如果不使用全部路径,VM无法知道你需要调用的是哪一个Scanner。就如同有两个张三,如果我清晰的指明是北京市什么什么区什么什么胡同的那个张三,你怎么区分呢?而位于同一个包中的类,我们不需要特意声明引入某个类,因为系统已经默认引入了这个包里的全部类。
那为什么我们对String的引用也不需要声明呢?因为String是java.lang包下的类,这个包是java的核心包,当虚拟机开始运行的时候,就会默认为我们导入这个包。
我们在编写java代码的时候,也要按照这个方式,将我们写的java类按包的形式分别存放。比如我们准备把SportStar这个类放在com.dyz.business这个包下面,我们就要在SportStar这个类的第一行加上下面的代码
package com.dyz.business;
我们准备把OfferServer这个类放在com.dyz.server这个包下面,我们就要在OfferServer的第一行加上
package com.dyz.server;
一个类只能由一个package语句,而且这个语句必须是在最前面的。在这之后,是我们需要导入的外部包,比如我们已经见过的Scanner。
导入类需要使用import关键字,语法是
import 第一层包.第二层包.第三层包.....包含所需引用类的包.所需引用类类名;
另外我们可以使用*来表示某一个包里的全部成员,比如 import java.util.*;这样引用后,java.util包里的所有的类都被导入了,但是由于这样会增加系统的压力,所以我们并不建议这样做。而且以后使用IDE编程,IDE工具会提醒我们要导入的包是具体的哪一个,十分方便。
如果不使用import关键字,我们也可以在具体调用类的时候加上类的全名,比如
java.util.Scanner scan = new java.util.Scanner(System.in);
这样做的好处是只需要在引用的时候来调用,而不需要初始化的时候就调用。但是缺点是你必须在很多地方写上全名,稍有错漏就会报错,而且现在很多第三方的包名实在是长...
类的存储在代码结构上和在物理结构上相同,比如我们把SportStar放在了com.dyz.business包下面,那么如果我们用javac -d E:myjavamyclass SportStar.java的命令去编译它,我们会发现它会在myclass文件夹下生成com包,然后在com包下面生成dyz包,然后在dyz包下面生成business包,最后再business包下面生成SportStar.class文件。
如果一个类前面没有使用package,那么这个类会被放置在一个默认包中(default),也叫未命名的包(unmanaed package),对这个类进行编译时,生成的class文件一定会在当前路径下。
到目前为止我们所有的代码都是在未命名包中,这是一个很不好的习惯,我们需要按照某种结构将我们的代码分类在不同包中,比如按照功能,或者按照分类。
上面我们提到使用 javac -d E:myjavamyclass SportStar.java 的命令来编译SportStar类,javac -d 的意思是指定class生成的路径,我们使用了E:myjavamyclass这个路径,这是一个绝对路径,如果我们每编译一个类都要这样写,那都得累死,所以我们可以使用相对路径 javac -d .myclass SportStar.java 一个点表示当前路径, .myclass表示当前路径下的myclass文件夹,由于我们当前路径就是在E:myjava这个文件夹下,所以这个可以直接使用当前路径,如果我们当前路径在C盘..那还是使用绝对路径吧 ....
使用了javac -d命令以后,class类文件被生成到了正确的包中,但是我们的java命令就不太方便了,我们需要使用
java -cp E:myclasscomdyzserver OfferServer来执行,或者使用
java -cp .myclass com.dyz.server.OfferServer 来执行
来源:https://blog.csdn.net/weixin_42250593