Java import 包(package)
解决问题:随着程序不断扩展,程序中就会出现同名称类。当使用有多个一样名称类时,就会出现冲突。程序不知道到底使用哪一个具体类!
解决方案:Java 引入了包(package)机制,提供了类的多层命名空间,用于解决类的命名冲突、类文件管理等问题。避免了名称上的冲突。
使用包优点:
1. 区分相同名称的类。
1. 能够较好地管理大量的类。
1. 控制访问范围。
包定义
ava 中使用 package 语句定义包,package 语句应该放在源文件的第一行,在每个源文件中只能有一个包定义语句,并且 package 语句适用于所有类型(类、接口、枚举和注释)的文件。定义包语法格式如下:package 包名;
Java 包的命名规则如下:
- 包名全部由小写字母(多个单词也全部小写)。
- 如果包名包含多个层次,每个层次用“.”分割。
- 包名一般由倒置的域名开头,比如 com.baidu,不要有 www。
- 自定义包不能 java 开头。
注意:如果在源文件中没有定义包,那么类、接口、枚举和注释类型文件将会被放进一个无名的包中,也称为默认包。在实际企业开发中,通常不会把类定义在默认包下。
包导入
不导包写法:example.Test test = new example.Test();
导包后写法:Test test = new Test();
导包主要为简化编程代码。上述代码导包示例:import example.Test;
导指定包下全部类:import example.*;
Java 默认为所有源文件导入 java.lang 包下的所有类,因此前面在 Java 程序中使用 String、System 类时都无须使用 import 语句来导入这些类。
在极端情况下:在同一类中使用不同包下的同名类,怎么办呢?
系统包
包 | 说明 |
---|---|
java.lang | Java 的核心类库,包含运行 Java 程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、异常处理和线程类等,系统默认加载这个包 |
java.io | Java 语言的标准输入/输出类库,如基本输入/输出流、文件输入/输出、过滤输入/输出流等 |
java.util | 包含如处理时间的 Date 类,处理动态数组的 Vector 类,以及 Stack 和 HashTable 类 |
java.awt | 构建图形用户界面(GUI)的类库,低级绘图操作 Graphics 类、图形界面组件和布局管理 (如 Checkbox 类、Container 类、LayoutManger 接口等),以及用户界面交互控制和事 件响应(如 Event 类) |
java.awt.image | 处理和操纵来自网上的图片的 Java 工具类库 |
java.wat.peer | 很少在程序中直接用到,使得同一个 Java 程序在不同的软硬件平台上运行 |
java.net | 实现网络功能的类库有 Socket 类、ServerSocket 类 |
java.lang.reflect | 提供用于反射对象的工具 |
java.util.zip | 实现文件压缩功能 |
java.awt.datatransfer | 处理数据传输的工具类,包括剪贴板、字符串发送器等 |
java.sql | 实现 JDBC 的类库 |
java.rmi | 提供远程连接与载入的支持 |
java. security | 提供安全性方面的有关支持 |
Java import static静态导入
JDK 1.5 之后增加了一种静态导入的语法;用于导入指定类的某个静态成员变量、方法或全部的静态成员变量、方法。如果一个类中的方法全部是使用 static 声明的静态方法,则在导入时就可以直接使用 import static 的方式导入。
import 和 import static 的作用,使用 import 可以省略写包名,而使用 import static 可以省略类名。
//格式:
import static package.ClassName.fieldName|methodName;
//静态导入Math类下的全部方法、字段
import static java.lang.Math.*;
//静态导入Math类下的sqrt方法
import static java.lang.Math.sqrt;
Java构造方法
构造方法是类的一种特殊方法,用来初始化类的一个新的对象,在创建对象(new 运算符)之后自动调用。Java 中的每个类都有一个默认的构造方法,如果类中显式地定义了一个或多个构造方法,则 Java 不再提供默认构造方法。并且可以有一个以上的构造方法。
构造方法必须满足要求:
1. 方法名必须与类名相同;
1. 可以有 0 个、1 个或多个参数;
1. 没有任何返回值,包括 void;
1. 默认返回类型就是对象类型本身;
1. 只能与 new 运算符结合使用;
注意:
1 . this()调用构造函数时必须放在构造函数的第一行代码位置!!!!
2 . 如果为构造方法定义了返回值类型或使用 void 声明构造方法没有返回值,编译时不会出错,但 Java 会把这个所谓的构造方法当成普通方法来处理。
3 . 构造方法不能被 static、final、synchronized、abstract 和 native(类似于 abstract)修饰。构造方法用于初始化一个新对象,所以用 static 修饰没有意义。构造方法不能被子类继承,用 final 和 abstract 修饰没有意义。多个线程不会同时创建内存地址相同的同一个对象,所以用 synchronized 修饰没有必要。
构造方法不是没有返回值吗?为什么不能用 void 声明呢?
这是 Java 的语法规定。实际上,类的构造方法是有返回值的,当使用 new 关键字来调用构造方法时,构造方法返回该类的实例,可以把这个类的实例当成构造器的返回值,因此构造器的返回值类型总是当前类,无须定义返回值类型。但必须注意不要在构造方法里使用 return 来返回当前类的对象,因为构造方法的返回值是隐式的。
public class Gamer {
public String name; // 姓名
private int age; // 年龄
// 定义带有一个参数的构造方法
public Gamer(String name) {
this.name = name;
}
// 定义带有两个参数的构造方法
public Gamer(String name,int age) {
this.name = name;
this.age = age;
}
public String toString() {
return "我是玩家,我叫"+name+",今年"+age+"岁。";
}
}
Java析构方法
析构方法与构造方法相反,当对象脱离其作用域时(例如对象所在的方法已调用完毕),系统自动执行析构方法。析构方法往往用来做清理垃圾碎片的工作,例如在建立对象时用 new 开辟了一片内存空间,应退出前在析构方法中将其释放。
在 Java 的 Object 类中还提供了一个 protected 类型的 finalize() 方法,因此任何 Java 类都可以覆盖这个方法,在这个方法中进行释放对象所占有的相关资源的操作。
对象的 finalize() 方法具有如下特点:
- 垃圾回收器是否会执行该方法以及何时执行该方法,都是不确定的。
- finalize() 方法有可能使用对象复活,使对象恢复到可触及状态。
- 垃圾回收器在执行 finalize() 方法时,如果出现异常,垃圾回收器不会报告异常,程序继续正常运行。
由于 finalize() 方法的不确定性,所以在程序中可以调用 System.gc() 或者 Runtime.gc() 方法提示垃圾回收器尽快执行垃圾回收操作。
public class Counter {
private static int count = 0; // 计数器变量
public Counter() {
// 构造方法
this.count++; // 创建实例时增加值
}
public int getCount() {
// 获取计数器的值
return this.count;
}
protected void finalize() {
// 析构方法
this.count--; // 实例销毁时减少值
System.out.println("对象销毁");
}
public static void main(String[] args) {
Counter cnt1 = new Counter(); // 建立第一个实例
System.out.println("数量:"+cnt1.getCount()); // 输出1
Counter cnt2 = new Counter(); // 建立第二个实例
System.out.println("数量:"+cnt2.getCount()); // 输出2
cnt2 = null; // 销毁实例2
try {
System.gc(); // 清理内存
Thread.currentThread().sleep(1000); // 延时1000毫秒
System.out.println("数量:"+cnt1.getCount()); // 输出1
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
Java创建与销毁
创建对象
显式创建对象
1. 使用 new 关键字创建对象;格式:类名 对象名 = new 类名();
1. 调用 java.lang.Class 或者[ java.lang.reflect.Constuctor ](https://segmentfault.com/a/1190000016511589)类的 newlnstance() 实例方法
//示例
Class<?> 类对象名称 = java.lang.Class.forName(要实例化的类全称);
类名 对象名 = (类名)Class类对象名称.newInstance();
Class<?> aClass = Class.forName("java.lang.String");//exception: java.lang.ClassNotFoundException
Object str = aClass.newInstance();//Exception, java.lang.IllegalAccessException
3. 调用对象的 clone() 方法;该方法不常用,使用该方法创建对象时,要实例化的类必须继承 java.lang.Cloneable 接口。调用对象的 clone() 方法创建对象。格式:类名 对象名 = (类名)已创建好的类对象名.clone();
3. 调用 java.io.ObjectlnputStream 对象的 readObject() 方法
注意事项:
- 使用 new 关键字或 Class 对象的 newInstance() 方法创建对象时,都会调用类的构造方法。
- 使用 Class 类的 newInstance() 方法创建对象时,会调用类的默认构造方法,即无参构造方法。
- 使用 Object 类的 clone() 方法创建对象时,不会调用类的构造方法,它会创建一个复制的对象,这个对象和原来的对象具有不同的内存地址,但它们的属性值相同。
- 如果类没有实现 Cloneable 接口,则 clone。方法会抛出 java.lang.CloneNotSupportedException 异常,所以应该让类实现 Cloneable 接口。
隐含创建对象
1. String strName = "strValue",其中的“strValue”就是一个 String 对象,由 Java 虚拟机隐含地创建。
1. 当 Java 虚拟机加载一个类时,会隐含地创建描述这个类的 Class 实例。
提示:类的加载是指把类的 .class 文件中的二进制数据读入内存中,把它存放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class 对象,用来封装类在方法区内的数据结构。
无论釆用哪种方式创建对象,Java 虚拟机在创建一个对象时都包含以下步骤:
- 给对象分配内存。
- 将对象的实例变量自动初始化为其变量类型的默认值。
- 初始化对象,给实例变量赋予正确的初始值。
注意:每个对象都是相互独立的,在内存中占有独立的内存地址,并且每个对象都具有自己的生命周期,当一个对象的生命周期结束时,对象就变成了垃圾,由 Java 虚拟机自带的垃圾回收机制处理。
销毁对象
在清除对象时,由系统自动进行内存回收,不需要用户额外处理。
Java 语言的内存自动回收称为垃圾回收(Garbage Collection)机制,简称 GC。垃圾回收机制是指 JVM 用于释放那些不再使用的对象所占用的内存。
Java 语言并不要求 JVM 有 GC,也没有规定 GC 如何工作。不过常用的 JVM 都有 GC,而且大多数 GC 都使用类似的算法管理内存和执行回收操作。具体的垃圾回收实现策略有很多种。如:标记 - 清除算法|整理算法、复制算法、分代算法等到。
注意:调用 System.gc() 或者 Runtime.gc() 方法也不能保证回收操作一定执行,它只是提高了 Java 垃圾回收器尽快回收垃圾的可能性。
在 Java 虚拟机的堆区,每个对象都可能处于以下三种状态之一。
1)可触及状态:当一个对象被创建后,只要程序中还有引用变量引用它,那么它就始终处于可触及状态。
2)可复活状态:当程序不再有任何引用变量引用该对象时,该对象就进入可复活状态。在这个状态下,垃圾回收器会准备释放它所占用的内存,在释放之前,会调用它及其他处于可复活状态的对象的 finalize() 方法,这些 finalize() 方法有可能使该对象重新转到可触及状态。
3)不可触及状态:当 Java 虚拟机执行完所有可复活对象的 finalize() 方法后,如果这些方法都没有使该对象转到可触及状态,垃圾回收器才会真正回收它占用的内存。
{
// 第一种情况:对象o的作用范围,超过这个范围对象将被视为垃圾
Object o = new Object();
// 第二种情况:对象被赋值为null将被视为垃圾
o = null;
}