让开始学java的我困惑的问题解析


前面已经对java一些基础概念进行了理解:

Java 包(package)详解

java中文件名、类名之间的关系

java中类的main方法总结


一个java文件中可以有多个class,但是只能有一个是public

public class HelloWorld {
    public static void main(String[] args) {

        int employee;
        String isSave;
        boolean hhh;


        final double PI = 3.14;

        final int y = 10;

        MyClass myclass = new MyClass();
        myclass.sayHello();

        System.out.println("Hello World");
    }
}

class MyClass {
    int a;
    byte b;
    char c;
    String s;

    public static void main(String[] args) {
        System.out.println("Hello World");
    }

    void sayHello() {
        System.out.println("say hello");
    }
}

从下面的图可以看出HelloWorld.java中包含两个class,HelloWorld和MyClass。

在test目录下新建一个class文件,自动会出现下面的内容

https://raw.githubusercontent.com/xkyvvv/blogpic2/main/img/image-20211222210328638.png

注意此时的 package test是自动出现的。

此时如果我们在HelloWorld的main函数中使用Mytest类,我们需要在前面引入这个类

//import test.MyTest1;

public class HelloWorld {
    public static void main(String[] args) {

        int employee;
        String isSave;
        boolean hhh;


        final double PI = 3.14;

        final int y = 10;

        MyClass myclass = new MyClass();
        myclass.sayHello();

        MyTest1 mytest1 = new MyTest1();

        System.out.println("Hello World");
    }
}

class MyClass {
    int a;
    byte b;
    char c;
    String s;

    public static void main(String[] args) {
        System.out.println("Hello World");
    }

    void sayHello() {
        System.out.println("say hello");
    }
}

如果去掉import test.MyTest1,运行程序则会报错:

image-20211222211102672

加上import test.MyTest1,程序可以正常运行:


java的package路径和实际目录的路径是什么关系?

我们先新建一个package

https://raw.githubusercontent.com/xkyvvv/blogpic2/main/img/image-20211222211728823.png

此时,我们到项目的实际目录下去看看

在这里插入图片描述

发现虽然我们是新建了一个package,实际上也是新建了一个目录。

我们继续在新建的package中,新建一个class,

image-20211222212252482

发现自动会出现package test.Mypackage;

此时在我们的HelloWorld的main函数中,如果想使用package中的MyP1类,我们需要在HelloWorld.java中前面加上import test.Mypackage.MyP1;

import test.MyTest1;

import test.Mypackage.MyP1;

public class HelloWorld {
    public static void main(String[] args) {

        int employee;
        String isSave;
        boolean hhh;


        final double PI = 3.14;

        final int y = 10;

        MyClass myclass = new MyClass();
        myclass.sayHello();

        MyTest1 mytest1 = new MyTest1();

        MyP1 myp1 = new MyP1();

        System.out.println("Hello World");
    }
}

class MyClass {
    int a;
    byte b;
    char c;
    String s;

    public static void main(String[] args) {
        System.out.println("Hello World");
    }

    void sayHello() {
        System.out.println("say hello");
    }
}

如果不加,则会报下面的错误,加上之后则可以正常运行。

image-20211222212955913

通过上面我们其实可以知道package和目录实际上是一个意思,只是在不同的语境下的不同解释。

现在我们可以这样理解了,有一个package/目录叫test,该package/目录下有一个package/目录叫Mypackage,Mypackage这个package/目录下有一个类文件,该类文件中只包含一个类MyP1。test这个ackage/目录下还有两个类文件,分别叫HelloWorld和MyTest1,HelloWorld文件下有HelloWorld和MyClass两个类,MyTest1文件下只有一个类MyTest1。

image-20211222214450722


每个java文件中只有一个是public的类,但是每个类中都可以有main函数,非public的类的main函数可以在我们单元测试的时候用。

https://raw.githubusercontent.com/xkyvvv/blogpic2/main/img/image-20211222215307163.png

从这张图片中我们可以知道每个类只要有main函数,都可以执行。

如果我们把类MyClass中的main函数删掉,则会发现这个类的绿色小三角形不存在了,也就不可以执行了。

https://raw.githubusercontent.com/xkyvvv/blogpic2/main/img/image-20211222215544922.png


java的import和C/C++的#include有什么区别?

即使这个源文件不在子目录com/mycompany下,也可以进行编译。如果它不依赖于其他包,就不会出现编译错误。但是,最终的程序将无法运行,这是因为虚拟机找不到类文件。(对于这部分我不是很懂,class文件不是就在那里吗,怎么就不能执行了,我自己试了一下的确如此。一定要目录结构对准,和用java来加载类的时候,必须用完整包名,即com.mycompany.xx来执行。)

Java允许使用包将类组织起来。借助于包可以方便地组织自己的代码,并将自己的代码与别人提供的代码库分开管理。使用包的主要原因是确保类名的唯一性。同名的类放置在不同的包中,就不会产生冲突。如同硬盘的目录嵌套一样,也可以使用嵌套层次组织包。

为了保证包名的绝对唯一性,Sun公司建议将公司的因特网域名以逆序的形式作为包名,并且对于不同的项目使用不同的子包。所以,我们经常在类库中看到一堆包名像这样的:com.sun和org.apache等等。

这里我要说明一下的就是不要认为import与C/C++中的#include是相同作用的。其实,java编译器可以查看其他文件的内部,所以根本不需要把文件的内容include进来,因此java不需要include机制,而只要告诉类文件在哪里就可以了。

其实,import语句唯一的好处是简捷。这说明我们完全可以不用import语句来写出所有程序,只不过这样会很麻烦而已。其实,Java的包机制与C++的命名空间(namespace)非常类似,都是用来防止重名冲突的。在Java中,package和import语句类似于C++中的namespace和using 指令。

注意,从编译器的角度来看,嵌套的包之间没有任何关系、例如,java.util包和java.util.jar包毫无关系。每一个都拥有独立的类集合。

还有,只要使用星号(*)来导入一个包,而不能使用import java.*来导入以java为前缀的所有包。而且,如果要同时使用两个类名相同的类,只能在使用的时候给出类的完整包名。

在包中定位类是编译器的工作。因此,class文件中的字节码是使用完整的包名来引用其他的类。这样JVM就会直接根据这个包名来找到对应的class文件。

import语句不仅可以导入类,还可以导入静态方法和静态域。例如通过import static java.lang.System.*;就可以使用System类的静态方法和静态域,而不必加类名前缀。

接着说下包作用域。标记为public的部分可以被任意的类使用。而如果没什么修饰符都没写,这个部分(类、方法和变量)就只可以被同一个包的所有方法访问。所以说,对于一个包,只有public的类才可以被其他包的类访问,其他的非公有类,你import了也没用!

JAR文件使用ZIP格式组织class文件和目录。

类路径就是Java编译器和JVM寻找class文件的默认路径。通常有:基目录/home/user/classdir、当前目录(.)和JAR文件目录/home/user/archives/archive.jar等等。


import的用法

包的概念
 包是Java语言提供的一种确保类名唯一性的机制,是类的一种组织和管理方式、是一组功能相似或相关的类或接口的集合。

一个完整的类名是包名+类名,在没有import导入的情况下,使用一个类需要给出完整的类名,如java.util.Date。为了方便,Java自动导入两个包:java.lang包和默认包。
无包的类可以访问有包的类, 直接导入即可;有包的类无法访问无包的类, 直接访问是访问同一个包中的, 而有包的类与无包的类不在一个包里。由于使用不同包中的类需要导入, 而无包的类因无包名无法导入;
Java的包表面上看(从路径上看)是有等级的,但实际上并没有,比如java.awt,java.awt.color是两个地位相同的包。java.awt.color并不属于java.awt。
在采用类名方式使用一个类的时候, 先在当前包中查找是否有这个类, 如果没有才去导入的包中找。

包的作用
方便组织自己的代码,并将自己的代码与别人提供的代码库分开管理。
将相关联的接口和类集合到一块。比如,package graphics; 就把图形处理相关的模块放到了一起。便于使用。
如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
实现了外界对包的访问控制。 需要先进行导入。

定义包
 要想将一个类放入一个包中,必须在源文件中除注释以外的第一行使用package+包名语句。同时将属于包的文件放在与完整的包名匹配的子目录中。当需要调用此包中的类时,就可以使用关键字import进行导入。如果源文件中没有使用package语句,这个源文件中的类就会被放置在一个默认包(default package)中。默认包是一个没有名字的包。

一、在定义包的时候,应该注意几点:

为了尽量使包名保持唯一性,包名通常采用小写、按倒写因特网域名的形式进行定义。
在进行命名包时,应该避免使用与系统发生冲突的名字。
一个源文件只能有一个package语句,放在源文件第一行,import语句前。
自定义包可以以java开头。

编译和运行
一、编译带包的类:

javac -d 目录 源文件名.java
注:在使用命令javac –d 之前,必须先创建好包路径,因为该命令不会自动创建文件夹。
1
2
二、运行带包的类:

java 包名.类名
1

使用包
 同个包的类之间访问比较简单,在代码中直接使用类名;而不同包之间的访问则必须满足一个条件:一个类如果希望被其他包中的类访问, 那么必须加上public修饰(注意:用public修饰的类必须和源文件名同名)。
一、不同包之间的使用通常有以下3种方法:只能导入public修饰的类

使用全名访问类;
import 该类;
import 包含该类的整个包;

常用的包
Java.lang包:java的核心类库,包含了运行java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等,系统缺省(默认)加载这个包。
java.util包:Java的实用工具类库。在这个包中,Java提供了一些实用的方法和数据结构。例如,Java提供日期(Data)类、日历(Calendar)类来产生和获取日期及时间,提供随机数(Random)类产生各种类型的随机数,还提供了堆栈(Stack)、向量(Vector) 、位集合(Bitset)以及哈希表(Hashtable)等类来表示相应的数据结构。
java.io包:java语言的标准输入/输出类库,如基本输入/输出流、文件输入/输出、过滤输入/输出流等。
java.util.zip包:实现文件压缩功能。
java.lang.reflect包:提供用于反射对象的工具。
java.mah:如提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。
java.net包:用来实现网络功能的类库。如Socket类、ServerSocket类。
java.awt包:构建图形用户界面(GUI)的类库。提供的类如:低级绘图操作Graphics类,图形界面组件和布局管理如 Checkbox类、Container类、LayoutManager接口等,以及用户界面交互控制和事件响应,如Event类。
java.awt.event包:GUI事件处理包。
java.awt.image包:处理和操纵来自于网上的图片的java工具类库。
java.sql包:实现JDBC的类库。
java.applet包:编写java applet程序用的。

  • 25
    点赞
  • 121
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小熊coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值