java面向对象学习--包
1.9k7 分钟
原文链接:https://www.cnblogs.com/Time25/p/19890707.html
为什么要有包这个东西
加入我写了一个Array,但是java的jdk也有一个Array,那这个时候该怎么办呢,名字冲突了啊,包就是来解决这个问题的,每个类其实都是属于某一个包的
Java定义了一种名字空间,称之为包:package。一个类总是属于某个包,类名(比如Person)只是一个简写,真正的完整类名是包名.类名。
在Java虚拟机执行的时候,JVM只看完整类名,因此,只要包名不同,类就不同。
包是没有什么继承关系的,比如java.util和java.util.zip是不同的包,两者没有任何继承关系。
包可以是多层结构,用.隔开。例如:java.util。
1 2 3 4 5 6 7 8
| 小军的Arrays类存放在包mr.jun下面,因此,完整类名是mr.jun.Arrays;
JDK的Arrays类存放在包java.util下面,因此,完整类名是java.util.Arrays。
package mr.jun; public class Arrays {
}
|
可以理解为,包就是一个文件夹
1 2 3 4 5 6 7 8 9 10 11 12
| 我们还需要按照包结构把上面的Java文件组织起来。假设以package_sample作为根目录,src作为源码目录,那么所有文件结构就是:
package_sample └─ src ├─ hong │ └─ Person.java │ ming │ └─ Person.java └─ mr └─ jun └─ Arrays.java hong就是一个包,ming也是一个包
|
包的作用域
先看代码
1 2 3 4 5 6 7 8
| package hello;
public class Person { void hello() { System.out.println("Hello!"); } }
|
1 2 3 4 5 6 7 8 9
| package hello;
public class Main { public static void main(String[] args) { Person p = new Person(); p.hello(); } }
|
之所以可以调用可以这样理解:就是hello这个方法没有任何的权限修饰,所以只要是在同一个包里的就可以使用,Person类和Main类都是在hello这个包里的,所以都可以访问hello方法
那什么时候不可以用呢
1 2 3 4 5 6 7
| package hello;
public class Person { void hello() { System.out.println("Hello!"); } }
|
1 2 3 4 5 6 7 8 9 10
| package world;
import hello.Person;
public class Other { void test() { Person p = new Person(); } }
|
这里就会报错,这个Other类不是在hello类里的,包就是不同的包,不会存在什么继承的关系什么的
import
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| 在一个class中,我们总会引用其他的class。例如,小明的ming.Person类,如果要引用小军的mr.jun.Arrays类,他有三种写法: 1.
package ming;
public class Person { public void run() { mr.jun.Arrays arrays = new mr.jun.Arrays(); } } 2.
package ming;
import mr.jun.Arrays;
public class Person { public void run() { Arrays arrays = new Arrays(); } }
3. 在写import的时候,可以使用*,表示把这个包下面的所有class都导入进来(但不包括子包的class):
package ming;
import mr.jun.*;
public class Person { public void run() { Arrays arrays = new Arrays(); } }
|
import static
可以导入一个类的静态字段和静态方法
1 2 3 4 5 6 7 8 9 10 11 12
| package main;
import static java.lang.System.*;
public class Main { public static void main(String[] args) { out.println("Hello, world!"); } }
|
在java编译中关于包的知识
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| Java编译器最终编译出的.class文件只使用完整类名,因此,在代码中,当编译器遇到一个class名称时:
如果是完整类名,就直接根据完整类名查找这个class; 如果是简单类名,按下面的顺序依次查找: 查找当前package是否存在这个class; 查找import的包是否包含这个class; 查找java.lang包是否包含这个class。
package test;
import java.text.Format;
public class Main { public static void main(String[] args) { java.util.List list; Format format = null; String s = "hi"; System.out.println(s); MessageFormat mf = null; } }
|
因此,编写class的时候,编译器会自动帮我们做两个import动作:
1.默认自动import当前package的其他class;
2.默认自动import java.lang.*。
值得注意的是:自动导入的是java.lang包,但类似java.lang.reflect这些包仍需要手动导入。
第一个怎么理解呢
就是假设你的pakage hello 下面写了这两个
那么你在写main函数的时候
1 2 3 4 5 6 7
| package hello;
public class Main { public static void main(String[] args) { Person p = new Person(); } }
|
第二个怎么理解
就是常用的类比如
1 2 3 4 5
| String(字符串) System(比如 System.out.println) Integer / Double(基本类型的包装类) Math(数学运算) Object(所有类的祖先)
|
如果没有这个设定的话
1 2 3 4 5
| import java.lang.String; import java.lang.System; import java.lang.Object; import java.lang.Math;
|
值得注意的是如果有两个class名称相同,例如,mr.jun.Arrays和java.util.Arrays,那么只能import其中一个,另一个必须写完整类名
一些开发中的小知识
要注意也不要和JDK常用类重名:
java.util.List
java.text.Format
java.math.BigInteger
要注意不要和java.lang包的类重名,即自己的类不要使用这些名字:
String
System
Runtime
为了避免名字冲突,我们需要确定唯一的包名。推荐的做法是使用倒置的域名来确保唯一性。
小疑惑:
在此之前自己写的小程序都是没有package的,那这些文件是在什么包里呢,就是在默认包里
1 2 3 4 5 6
| src ├─ Hello.java <-- 没有写 package,属于默认包 ├─ Test.java <-- 没有写 package,属于默认包 └─ com └─ hong └─ Person.java <-- 属于 com.hong 包
|
好处是:同一个包互相认识: 如果 Hello.java 和 Test.java 都没有写 package,它们都在“默认包”里,所以它们互相之间可以直接调用,不需要 import。
坏处是:无法被“有名有姓”的包引用(致命伤):
这是一个非常重要的规则:如果一个类在“默认包”里,那么住在“有名有姓”的包(比如 com.hong)里的类,是无法通过 import 来调用它的。
例子: Person.java (在 com.hong 包里) 永远无法使用 Hello.java (在默认包里),因为默认包没有名字,没法写 import ???.Hello;。
// TRAINING LOG · 第 53 / 76 篇训练记录 · 成文于 2026.04.19 · 下午 15:17