深入解析Java的包(package)

虽然 Java 语言是典型的面向对象编程语言,但其中的八种基本数据类型并不支持面向对象编程,基本类型的数据不具备“对象”的特性——不携带属性、没有方法可调用。 沿用它们只是为了迎合人类根深蒂固的习惯,并的确能简单、有效地进行常规数据处理。

这种借助于非面向对象技术的做法有时也会带来不便,比如引用类型数据均继承了 Object 类的特性,要转换为 String 类型(经常有这种需要)时只要简单调用 Object 类中定义的toString()即可,而基本数据类型转换为 String 类型则要麻烦得多。为解决此类问题 ,Java为每种基本数据类型分别设计了对应的类,称之为包装类(Wrapper Classes),也有教材称为外覆类或数据类型类。

每个包装类的对象可以封装一个相应的基本类型的数据,并提供了其它一些有用的方法。包装类对象一经创建,其内容(所封装的基本类型数据值)不可改变。

基本类型和对应的包装类可以相互装换:
由基本类型向对应的包装类转换称为装箱,例如把 int 包装成 Integer 类的对象;
包装类向对应的基本类型转换称为拆箱,例如把 Integer 类的对象重新简化为 int。
包装类的应用

八个包装类的使用比较相似,下面是常见的应用场景。
1) 实现 int 和 Integer 的相互转换

可以通过 Integer 类的构造方法将 int 装箱,通过 Integer 类的 intValue 方法将 Integer 拆箱。例如:

public class Demo {
  public static void main(String[] args) {
    int m = 500;
    Integer obj = new Integer(m); // 手动装箱
    int n = obj.intValue(); // 手动拆箱
    System.out.println("n = " + n);

    Integer obj1 = new Integer(500);
    System.out.println("obj 等价于 obj1?" + obj.equals(obj1));
  }
}

运行结果:

n = 500
obj 等价于 obj1?true

2) 将字符串转换为整数

Integer 类有一个静态的 paseInt() 方法,可以将字符串转换为整数,语法为:

parseInt(String s, int radix);

s 为要转换的字符串,radix 为进制,可选,默认为十进制。

下面的代码将会告诉你什么样的字符串可以转换为整数:

public class Demo {
  public static void main(String[] args) {
    String str[] = {"123", "123abc", "abc123", "abcxyz"};

    for(String str1 : str){
      try{
        int m = Integer.parseInt(str1, 10);
        System.out.println(str1 + " 可以转换为整数 " + m);
      }catch(Exception e){
        System.out.println(str1 + " 无法转换为整数");
      }
    }
  }
}

运行结果:

123 可以转换为整数 123
123abc 无法转换为整数
abc123 无法转换为整数
abcxyz 无法转换为整数

3) 将整数转换为字符串

Integer 类有一个静态的 toString() 方法,可以将整数转换为字符串。例如:

public class Demo {
  public static void main(String[] args) {
    int m = 500;
    String s = Integer.toString(m);
    System.out.println("s = " + s);
  }
}

运行结果:

s = 500

自动拆箱和装箱

上面的例子都需要手动实例化一个包装类,称为手动拆箱装箱。Java 1.5(5.0) 之前必须手动拆箱装箱。

Java 1.5 之后可以自动拆箱装箱,也就是在进行基本数据类型和对应的包装类转换时,系统将自动进行,这将大大方便程序员的代码书写。例如:

public class Demo {
  public static void main(String[] args) {
    int m = 500;
    Integer obj = m; // 自动装箱
    int n = obj; // 自动拆箱
    System.out.println("n = " + n);

    Integer obj1 = 500;
    System.out.println("obj 等价于 obj1?" + obj.equals(obj1));
  }
}

运行结果:

n = 500
obj 等价于 obj1?true

自动拆箱装箱是常用的一个功能,读者需要重点掌握。

包不但可以包含类,还可以包含接口和其他的包。

目录以"\"来表示层级关系,例如 E:\Java\workspace\Demo\bin\p1\p2\Test.java。

包以"."来表示层级关系,例如 p1.p2.Test 表示的目录为 \p1\p2\Test.class。
如何实现包

通过 package 关键字可以声明一个包,例如:

  package p1.p2;

必须将 package 语句放在所有语句的前面,例如:

package p1.p2;
public class Test {
  public Test(){
    System.out.println("我是Test类的构造方法");
  }
}

表明 Test 类位于 p1.p2 包中。
包的调用

在Java中,调用其他包中的类共有两种方式。
1) 在每个类名前面加上完整的包名

程序举例:

public class Demo {
  public static void main(String[] args) {
    java.util.Date today=new java.util.Date();
    System.out.println(today);
  }
}

运行结果:

Wed Dec 03 11:20:13 CST 2014

2) 通过 import 语句引入包中的类

程序举例:

import java.util.Date;
// 也可以引入 java.util 包中的所有类
// import java.util.*;
public class Demo {
  public static void main(String[] args) {
    Date today=new Date();
    System.out.println(today);
  }
}

运行结果与上面相同。

实际编程中,没有必要把要引入的类写的那么详细,可以直接引入特定包中所有的类,例如 import java.util.*;。
类的路径

Java 在导入类时,必须要知道类的绝对路径。

首先在 E:\Java\workspace\Demo\src\p0\ 目录(E:\Java\workspace\Demo\src\ 是项目源文件的根目录)下创建 Demo.java,输入如下代码:

package p0;
import p1.p2.Test;
public class Demo{
  public static void main(String[] args){
    Test obj = new Test();
  }
}

再在 E:\Java\workspace\Demo\src\p1\p2 目录下创建 Test.java,输入如下代码:

package p1.p2;
public class Test {
  public Test(){
    System.out.println("我是Test类的构造方法");
  }
}

假设我们将 classpath 环境变量设置为 .;D:\Program Files\jdk1.7.0_71\lib,源文件 Demo.java 开头有 import p1.p2.Test; 语句,那么编译器会先检查 E:\Java\workspace\Demo\src\p0\p1\p2\ 目录下是否存在 Test.java 或 Test.class 文件,如果不存在,会继续检索 D:\Program Files\jdk1.7.0_71\lib\p1\p2\ 目录,两个目录下都不存在就会报错。显然,Test.java 位于 E:\Java\workspace\Demo\src\p1\p2\ 目录,编译器找不到,会报错,怎么办呢?

可以通过 javac 命令的 classpath 选项来指定类路径。

打开CMD,进入 Demo.java 文件所在目录,执行 javac 命令,并将 classpath 设置为 E:\Java\workspace\Demo\src,如下图所示:

运行Java程序时,也需要知道类的绝对路径,除了 classpath 环境变量指定的路径,也可以通过 java 命令的 classpath 选项来增加路径,如下图所示:

注意 java 命令与 javac 命令的区别,执行 javac 命令需要进入当前目录,而执行 java 命令需要进入当前目录的上级目录,并且类名前面要带上包名。

可以这样来理解,javac是一个平台命令,它对具体的平台文件进行操作,要指明被编译的文件路径。而java是一个虚拟机命令,它对类操作,即对类的描述要用点分的描述形式,并且不能加扩展名,还要注意类名的大小写。

这些命令比较繁杂,实际开发都需要借助 Eclipse,在Eclipse下管理包、编译运行程序都非常方便。Eclipse 实际上也是执行这些命令。
包的访问权限

被声明为 public 的类、方法或成员变量,可以被任何包下的任何类使用,而声明为 private 的类、方法或成员变量,只能被本类使用。

没有任何修饰符的类、方法和成员变量,只能被本包中的所有类访问,在包以外任何类都无法访问它。

(0)

相关推荐

  • 深入解读Java代码组织中的package包结构

    如果我们在Class对象上调用getPackage方法,就可以得到描述该类所在包的Package对象(Package类是在java.lang中定义的).我们也可以用包名通过调用静态方法getPackage或者调用静态方法getPackages(该方法返回由系统中所有已知包构成的数组)来获得Package对象.getName方法可以返回包的全名. Package对象的使用与其他反射类型完全不同,即我们不能在运行时创建或操纵包.我们可以使用Package对象来获取有关包的信息,诸如包的用途.谁创建了

  • Java基础教程之包(package)

    我们已经写了一些Java程序.之前的每个Java程序都被保存为一个文件,比如Test.java.随后,该程序被编译为Test.class.我们最终使用$java Test来运行程序. 然而,在一个正常的Java项目中,我们往往需要编写不止一个.java程序,最终的Java产品包括了所有的Java程序.因此,Java需要解决组织Java程序的问题.包(package)的目的就是为了更好的组织Java程序. 包的建立 包的建立非常简单.我们只用在Java程序的开始加入package就可以了.我们以H

  • java入门概念个人理解之package与import浅析

    由于近来学习java,遇到了一些在c++上没有的概念,将它记录下,以自己复习使用,如有不理解妥之处,望大家批评指导.资料均由网上经过自己整合理解而来,如有侵权请通知我将起删除即可. 我就以package与import开始吧. package的作用其实就是c++的namespace的作用,防止名字相同的类产生冲突,只是实现的机制不一样,java编译器在编译时,直接根据package 指定的信息直接将生成的class文件生成到对应目录下.如package aaa.bbb.ccc 编译器就将该.jav

  • 详解Java类库的概念以及import的使用方法

    Java类库及其组织结构(Java API) Java 官方为开发者提供了很多功能强大的类,这些类被分别放在各个包中,随JDK一起发布,称为Java类库或Java API. API(Application Programming Interface, 应用程序编程接口)是一个通用概念. 例如我编写了一个类,可以获取计算机的各种硬件信息,它很强大很稳定,如果你的项目也需要这样一个功能,那么你就无需再自己编写代码,将我的类拿来直接用就可以.但是,我的类代码很复杂,让你读完这些代码不太现实,而且我也不

  • Java 基础语法之解析 Java 的包和继承

    目录 一.包 1. 概念 2. 使用方式 3. 静态导入 4. 创建包 5. 包的访问权限 6. 常见的系统包 二.继承 1. 概念 2. 语法规则(含 super 使用) 3. protected 关键字 4. 更复杂的继承关系 5. final 关键字 三.组合 四.总结(含谜底) 一.包 1. 概念 根据定义:包是组织类的一种方式 那么为什么要组织类呢? 简单来讲就是保证类的唯一性,就比如在以后的工作中,如果大家一起开发一个项目,大家可能在自己的代码中都写到了一个 Test 类,而如果出现

  • 深入解析Java的包(package)

    虽然 Java 语言是典型的面向对象编程语言,但其中的八种基本数据类型并不支持面向对象编程,基本类型的数据不具备"对象"的特性--不携带属性.没有方法可调用. 沿用它们只是为了迎合人类根深蒂固的习惯,并的确能简单.有效地进行常规数据处理. 这种借助于非面向对象技术的做法有时也会带来不便,比如引用类型数据均继承了 Object 类的特性,要转换为 String 类型(经常有这种需要)时只要简单调用 Object 类中定义的toString()即可,而基本数据类型转换为 String 类型

  • 详解Java编程中包package的内容与包对象的规范

    包的内容 包的内容应该仔细设计,使其只包含在功能上相关的类和接口.包中的类可以自由地访问该包中其他类的非私有成员,有些类甚至可能有足够的权限去访问其他类的内部细节,为了避免这样的类对类成员进行误操作,我们需要对类成员进行保护.任何没有被声明为private的成员都可以被同一个包中的其他所有类型访问,所以任何不相关的类之间的藕合程度都可能会比我们所期望的程度高. 包还为寻找有用的接口和类的程序员提供了逻辑分组的功能.由不相关的类组成的包使程序员很难分辨出哪些接口和类是有用的,而类的逻辑分组可以帮助

  • java获取包下被指定注解的类过程解析

    方案一: 采用reflections 框架(此框架依赖com.google.guava) 1.reflections框架地址:https://github.com/ronmamo/reflections 2.项目依赖 <dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>0.9.11</versi

  • Java由浅入深带你了解什么是包package

    目录 什么是包 1.导入包中的类 2.静态导入 3.将类放到包中 4.包的访问权限控制 5.常见的系统包 什么是包 包 (package) 是组织类的一种方式. 使用包的主要目的是保证类的唯一性. 例如, 你在代码中写了一个 Test 类. 然后你的同事也可能写一个 Test 类. 如果出现两个同名的类, 就会冲突, 导致 代码不能编译通过 1.导入包中的类  Java 中已经提供了很多现成的类供我们使用 ①:例如打印数组: public class TestDemo{ public stati

  • JDK的Parser来解析Java源代码详解

    在JDK中,自带了一套相关的编译API,可以在Java中发起编译流程,解析Java源文件然后获取其语法树,在JDK的tools.jar(OSX下可以在/Library/Java/JavaVirtualMachines/jdk_version/Contents/Home/lib中找到)中包含着这整套API,但是这却不是Oracle和OpenJDK发布中的公开API,因此对于这套API,并没有官方的正式文档来进行说明.但是,也有不少项目利用了这套API来做了不少事情,例如大名鼎鼎的lombok使用了

  • 深入解析Java的Spring框架中bean的依赖注入

    每一个基于java的应用程序都有一个共同工作来展示给用户看到的内容作为工作的应用几个对象.当编写一个复杂的Java应用程序,应用程序类应该尽可能独立其他Java类来增加重复使用这些类,并独立于其他类别的测试它们,而这样做单元测试的可能性.依赖注入(或有时称为布线)有助于粘合这些类在一起,同时保持他们的独立. 考虑有其中有一个文本编辑器组件的应用程序,要提供拼写检查.标准的代码将看起来像这样: public class TextEditor { private SpellChecker spell

  • 解析Java虚拟机中类的初始化及加载器的父委托机制

    类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始化: 2.在静态代码块中进行初始化. 没有经过显式初始化的静态变量将原有的值. 一个比较奇怪的例子: package com.mengdd.classloader; class Singleton { // private static Singleton mInstance = new Singleton();// 位置1 // 位置1输

  • 深入解析Java编程中final关键字的作用

    final class 当一个类被定义成final class,表示该类的不能被其他类继承,即不能用在extends之后.否则在编译期间就会得到错误. package com.iderzheng.finalkeyword; public final class FinalClass { } // Error: cannot inherit from final class PackageClass extends FinalClass { } Java支持把class定义成final,似乎违背了

随机推荐