Java面向对象之包和内部类

包机制

包的定义

为什么需要包?

  • Windows树形文件系统
    • 文档分门别类,易于查找和管理
    • 使用目录解决文件同名冲突问题
  • 如何存放两个同名的类而不冲突
    • 使用包:package
    • 包对应Java源文件的目录结构

包的命名

  • 包名由小写字母组成,不能以圆点开头或结尾 package mypackage;
  • 包名之前最好加上唯一的前缀,通常使用组织倒置的网络域名 package net.javagroup.mypackage;
  • 包名后续部分。依不同机构内部的规范不同而不同 package net.javagroup.research.powerproject;

包的作用

  • 允许类组成较小的单元(类似文件夹),易于找到和使用相应的文件
  • 防止命名冲突区分名字相同的类
  • 有助于实施访问权限控制

import导包

为了使用不在同一包中的类,需要在Java程序中使用import关键字导入这个类

import 包名.类名;

例如:

import java.util.*; // 导入java.util包中所有类
import com.huawei.example.Book; // 导入指定包中的指定类

注意事项:

  • 使用包的注意事项
    • 一个类同时引用了两个来自不同包的同名类,必须通过完整类名来区分
  • 每个包都是独立的,顶层包不会包含子包的类
  • package和import的顺序是固定的
    • package必须位于第一行(忽略注释行)
    • 只允许有一个package语句
    • 其次是import
    • 接着是类的声明

Java常用包

作为Java语言的使用者,我们可以感受到Java语言的优势(平台无关、面向对象、多线程、高效易扩展等),而且它有很多已经实现的类库可以供我们直接使用,这些类库都是以jar包的形式提供的。它们共同构成了Java API,为编程者实现了各种常用操作的方法,为程序员编写Java程序代码带来了许多方便。

对于Java初学者,首先要学习和掌握Java中最常用的一些基础类库,然后通过做项目不断的掌握和应用,并逐步的学习、钻研底层的设计原理。

在Java众多的API中,目前使用较多的jar包如下表所示:

包名内容概述
java.lang提供java语言程序设计的基础类
java.util提供处理日期、时间、随机数生成等各种使用工具的类
java.io提供与输入输出相关的类
java.net提供实现网络操作相关的类
java.sql提供使用访问并处理存储在数据库中的数据的API
java.nio为输入输出提供缓冲区的类
java.text提供处理文本、日期、数字和消息的类和接口
java.awt包含用于创建用户界面和绘制图形图像的所有类
javax.swing提供一组与AWT功能相同的纯java的组件类

java.lang.*

java.lang包是java语言体系中其他类库的基础,已经内嵌到java虚拟机中,而且以对象的形式创建好了,所以我们在使用java.lang包时不需要再使用import将其导入,可以直接使用java.lang包中的所用类,以及直接引用某个类中的常量、变量和方法。

  • lang包下常用的类:
    • String:封装了与字符串类型相关的操作方法
    • Class:用于描述正在运行的java应用程序中的类和接口的状态
    • ClassLoader:用于加载类的对象
    • Enum:用于定义枚举类型
    • Math:用于实现基本数学运算
    • Number:抽象类,是基本数据类型类的父类
    • Object:所有java类的根类
    • Package:封装了有关java包的实现和规范的版本信息
    • Runtime:Runtime类对象使java应用程序与其运行环境相连接
    • StringBuffer:用于可变字符串的操作
    • StringBuilder:创建可变的字符串对象
    • System:封装了一些与java虚拟机系统相关的方法
    • Thread:创建和控制线程
    • ThreadGroup:创建和控制线程
    • Throwable:定义了java中的所有错误或者异常的父类
    • Process:定义了一个进程process对象,通过Runtime类中的exec方法启动该进程对象
  • lang包下常用的接口:
    • Appendable:用于追加字符串
    • Cloneable:用于复制类对象
    • Runnable:用于实现类对象具有线程功能
    • Comparable:用于类对象的排序

java.util.*

包包含集合框架、collection类、事件模型、日期和时间设施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组、日期Date类、堆栈Stack类、向量Vector类等)。集合类、时间处理模式、日期时间工具等各类常用工具包。

java.io.*

Java的核心库java.io提供了全面的IO接口。包括:文件读写、标准设备输入等。Java中IO是以流为基础进行输入输出的,所有数据被串行化写入输出流,或者从输入流读入。

java.net.*

主要用于处理以下抽象:

  • 地址:也就是网络标识符,如IP地址
  • 套接字:也就是基本双向数据通信机制
  • 接口:用于描述网络接口
  • URI:表示统一资源标识符
  • URL:表示统一资源定位符
  • 连接:表示到URL所指向资源的连接
  • InetAddress 类是对IP(Internet 协议)地址的抽象。它拥有两个子类:
    • 用于IPv4地址的:Inet4Address
    • 用于IPv6地址的:Inet4Address

java.sql.*

提供使用Java语言访问并处理存储在数据源(通常是一个关系数据库)中的数据的API。此API包括一个框架,凭借此框架可以动态地安装不同驱动程序来访问不同数据源

创建jar包

使用Eclipse把项目导成jar包

用命令创建jar包

  1. 编写java源码文件

  2. 使用javac编译生成class文件

  3. 将所有要打包的class文件存在的目录以及依赖的jar包全部放在一个根文件夹里面(比如bin)

  4. 编写MANIFEST清单文件,指定程序入口以及其他添加的依赖的jar包

  5. 执行打包指令:jar {ctxu} [vfm0M] [jar-文件名] [manifest-文件名] [-C 目录] 文件名 ...

    • 例如:jar cvfm xxx.jar MANIFEST.MF -C bin/ .

    命令含义:

    • -c 创建新的JAR文件包
    • -v 生成详细报告并打印到标准输出
    • -f 指定JAR文件名,通常这个参数是必须的
    • -m 指定需要包含的MANIFEST清单文件
MANIFEST文件介绍

MANIFEST文件对于jar打包都是必须的。MANIFEST文件描述了打包后的jar文件的详细信息,存在于打包后的META-INF的文件夹。一个简单的MANIFEST文件主要内容如下:

Manifest-Version: 1.0
Created-By: 1.8_0_172(Oracle Corporation)
Main-Class: com.huawei.main.TestMain

Mainfest-Version, Main-Class, Class-Path这三个属性在制作jar包时非常重要。

  • Manifest-Version 是版本号
  • Main-Class 则是jar包的入口程序,指定运行的类的全称(一定要包含包名),这样可以使用 java -jar name.jar 直接运行jar包
  • Class-Path是指的打包时需要依赖的其他jar包,打包的时候自己的程序中也可能含有其他的jar包所以要添加依赖。
  • 注意:每个MANIFEST属性冒号于内容之间都有一个空格,并且写完后最后还要留有一行空行,不然运行时还是出现找不到清单属性的错误。

权限访问控制

在Java中,针对类、成员方法和属性提供了四种访问级别,分别是private、default、protected和public

  • private(当前类访问级别):对于私有成员变量和方法,只有本类中创建该类的对象时,这个对象才能访问自己的私有成员变量和类中的私有方法
  • default(包访问级别):类的成员变量和方法什么修饰符都没有,又叫包修饰符,只有类本身成员和当前包下类的成员可以访问
  • protected(子类访问级别):用protected修饰的成员变量和方法能被该类的成员以及其子类成员访问,还可以被同一个包中其他类的成员访问
  • public(公共访问级别):这是一个最宽松的访问控制级别,如果一个类或者类的成员被public访问控制符修饰,那么这个类或者类的成员能被所有的类访问,不管访问类与被访问类是否在同一个包中
修饰符同一个类中同一个包中子类中任何地方
private×××
default××
protected×
public

访问级别

image20210721203707981.png

编写代码时,如果没有特殊的考虑,建议这样使用权限:

  • 成员变量使用private,隐藏细节
  • 构造方法用public,方便创建对象
  • 成员方法使用public,方便调用方法

内部类

内部类的定义

什么是内部类?

在Java中,允许在一个类的内部定义类,这样的类称作内部类,这个内部类所在的类称作外部类。

内部类分类

  • 成员内部类
  • 局部内部类
  • 静态内部类
  • 匿名内部类

成员内部类

定义: 在一个类中除了可以定义成员变量、成员方法,还可以定义类,这样的类被称作成员内部类。

说明:在成员内部类中,可以访问外部类的所有成员,包括成员变量和成员方法;在外部类中,同样可以访问成员内部类的变量和方法。

创建内部类对象的具体语法格式如下:

外部类名.内部类名 变量名 = new 外部类名().new 内部类名();

局部内部类

定义:局部内部类,也叫做方法内部类,就是定义在某个局部范围中的类,它和局部变量一样,都是在方法中定义的,其有效范围只限于方法内部。

说明:在局部内部类中,局部内部类可以访问外部类的所有成员变量和方法,而局部类中的变量和方法却只能在创建该局部内部类的方法中进行访问。

静态内部类

定义:所谓静态内部类,就是使用static关键字修饰的成员内部类

说明:静态内部类在成员内部类前增加了static关键字,在功能上,静态内部类中只能访问外部类的静态成员,同时通过外部类访问静态内部类成员时,可以跳过外部类从而直接通过内部类访问静态内部类成员。

创建静态内部类对象的具体语法格式如下:

外部类名.静态内部类名 变量名 = new 外部类名.静态内部类名();

匿名内部类

定义:匿名内部类其实就是没有名称的内部类

说明:在调用包含又接口类型参数的方法时,通常为了简化代码,可以直接通过匿名内部类的形式传入一个接口类型参数,在匿名内部类中直接完成方法的实现。

创建匿名内部类对象的具体语法格式如下:

new 父接口(){
    // 匿名内部类实现部分
}

注意:从JDK 8开始,允许在局部内部类、匿名内部类中访问非final修饰的局部变量,而JDK 8之前,局部变量前必须加final修饰符,否则程序编译报错。

Q.E.D.