Java程序设计-- 第3章 数组、引用、枚举和注解
3.1.1 初识数组
数组是一组具有相同类型的有序数据组成的集合。
数组中的一个数据成员称为数组元素,通过数组名+下标来唯一确定。
每个数组元素类似于一个普通变量,可以用来保存数据,所以数组是有序变量的集合。
Java中数组的元素类型可以是简单的数据类型,也可以是类。
3.1.2 一维数组
1.定义数组
数组元素类型 数组名[]; 或 数组元素类型 [] 数组名;
int a[]; (或int[] a;) //声明一个一维整型的数组a
char b[]; (或char[] b;) //声明一个一维字符型的数组b
double c[]; (或double[] c;) //声明一个一维双精度实型的数组c
注意:Java定义数组时,不会为数组分配存储空间。因此,数组声明时,是不指明长度的。
2.生成数组
数组名=new 数组元素类型[数组长度];
char s[];s=new char[5];
int temp[]=new int[10];
3.初始化数组
使数组中的每个元素有确定的数值
int s[];
s=new int[3];
s[0]=1;s[1]=2;s[2]=3;
int s[]={1,2,3};
//此时数组的长度由给定初值的个数自动决定。
注意:数组不能整体进行赋值。
访问一维数组
数组元素的访问可通过数组名加下标来实现:
数组名[下标]
如数组temp:
temp[0],temp[1],…,temp[9]
分别表示引用数组的第1个到第10个元素
注意:数组的下标是从0开始,到数组长度减1。数组长度可以通过“数组名.length”来获取。
实用案例【求一维数组的最大值及位置】
public class MaxNum{
public static void main(String[] args){
final int ARRAY_SIZE = 10;
int a[] = new int[ARRAY_SIZE];
int max = 0;
int index = 0;
for(int i=0;i<a.length;i++){
a[i]=(int)(Matn.random()*10);
Syetem.out.print(" "+a[i]);
}
System.out.println();
max=a[0];
for(int j=1;j<ARRAY_SIZE;j++){
if(a[j]>max)//判断当前位置的数是否大于最大值max
{
max = a[j];
index = j;
}
}
System.out.println("A["+index+"] has maximum value "+a[index]);
}
}
3.1.3 二维数组
数组的下标数也称为数组的维数,维数大于1的数组叫多维数组。
多维数组的使用方法基本类似,下面我们以二维数组为例进行分析。
二维数组可看作是特殊的一维数组,即:二维数组中每一个元素又是一个一维数组。
利用二维数组可以更方便地处理表格、空间形式的数据,如(x,y)坐标系中的点。
1.定义数组
数组元素类型 数组名 [] []; 或 数组元素类型 [] [] 数组名;
2.生成数组
数组名=new 数组元素类型[数组长度] [];
char s[][];s=new char[5][2];
int temp[][]=new int[10][10];
3.初始化数组
使数组中的每个元素有确定的数值
int s[][];
s=new int[3][3];
s[1][1]=1;s[1][2]=2;s[1][3]=3;
注意:
(1) 等式右边大括号内嵌套的大括号不能省,它代表数组的一行;
(2) 允许每个二维数组成员的长度不同,如int a[ ][ ]={{1,2},{3,4,5},{6,7,8}}
(3) 系统根据初始值自动确定数组长度和内存空间大小,如上面数组a的第二维长度分别为2,3,3。
4.二维数组的使用:和一维数组类似
引用二维数组元素基本方式为:
数组名[下标1][下标2]
//可以通过length属性求每一维数组的长度,如:
int temp[][]=new int[3][5];
System.out.println(temp.length); // 求二维数组的长度实际是求它的行数3
System.out.println(temp[0].length);//temp[0]的长度为5
实用案例【求二维数组中各元素的和】
package code0303;
public class SumAll{
public static void main(String args[]){
int total=0;
int arr[][]=new int[3][4];
for(int i=0;i<arr;i++){ //初始化并显示二维数组
for(int j=0;j<arr[i].length;j++){
arr[i][j]=i+j;
System,out,print(" "+arr[i][j]);
}
System.out.println();
}
for(int i=0;i<arr.length;i++)
for(int j=0;i<arr[i].length;j++){
total=total+arr[i][j];
}
System.out.println("The Sum is:"+total);
}
}
//程序运行结果
0 1 2 3
1 2 3 4
2 3 4 5
The Sum is:30
3.1.4 Array类
为方便数组的使用,Java在包java.util定义了一个叫Arrays的类。
Arrays类提供了多个操作数组的静态方法:
static type[] copyOf (type[] original,int length)
将original数组复制为一个新数组,其中length为新数组的长度。
static int binarySearch(type[] a,type key)
使用二分搜索法在数组a中搜索指定值key;
static boolean equals(type[] a,type[] b)
比较两个数组是否相等;
static void fill (type[] a, type val)
用一个指定的值val填充数组a;
static void fill (type[] a, int fromIndex, int toIndex, type val)
与前一个方法类似,但填充时仅仅针对下标为fromIndex到toIndex-1的数组元素赋值为val;
static void sort(type[] a)
对数组a排序;
实用案例【Arrays类的基本使用】
public class ArraysDemo {
public static void main(String[] args) {
Integer array[] = new Integer[9];
for(inti= 1;i< 10;i++)
array[i- 1] = (int) (Math.random()*100);
//显示,排序数组
System.out.print("原内容: ");
display(array);
Arraysort(array);
System.out.print("排序后: ");
display(aray);
//将值-1分配给数组array中下标从0到3-1位置上的元素
Arrays.fill(array,0,3,-1); .
System.out.print("执行fill()后:");
display(array); .
//搜索39
System.out.print("值39的位置 ");
int index= Arrays.binarySearch(array,39);
System.out.println(index);
}
static void display(Integer array[]) {
for (int i=0;i < array.length;i++)
System.out.print(array[i]+" ");
System.out.println("");
}
}
//程序运行结果
原内容:90 48 81 14 3 35 95 4 97
排序后:3 4 14 35 48 81 90 95 97
执行fill()后:-1 -1 -1 35 48 81 90 95 97
值39的位置 -5
3.2 引用Java中的四种引用
1.强引用
如果一个对象具有强引用,它就不会被垃圾回收器回收;
即使当前内存空间不足,JVM也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止;
如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null;JVM在合适的时间就会回收该对象,具体什么时候收集这要取决于具体的垃圾回收器。
形式:Object strongReference = new Object(); // 强引用
或者:String str = “hello”; // 强引用
str = null; // 取消强引用
2.软引用
在使用软引用时,如果内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收;
只有在内存空间不足时,软引用才会被垃圾回收器回收;
JDK 提供了 SoftReference 类来表示软引用;
软引用在被垃圾回收时,也遵循LRU法则,优先回收最近最少被使用的对象进行回收。
SoftReference<String> softName = new SoftReference<>(“张三”);//软引用
或者:
String str = new String(“张三”); //强引用
SoftReference<String> softReference = new SoftReference<>(str); //软引用
3.弱引用
如果一个对象只具有弱引用,其生命周期相比于软引用更加短暂;
在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会对它进行回收。
不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象;
JDK 提供了 WeakReference 类来表示弱引用;
WeakReference <String> weakName = new WeakReference <>(“张三”);//弱引用
或者:
String str = new String(“张三”); //强引用
WeakReference <String> weakName = new WeakReference <>(str); //弱引用
4.虚引用- PhantomReference
虚引用与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收;
虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
虚引用主要用来跟踪对象被垃圾回收器回收的活动,程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要进行垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动,也可以理解为一种回调方法。
ReferenceQueue<String> queue = new ReferenceQueue<String>();
PhantomReference<String> pr = new PhantomReference<String>(new String(“hello”), queue); //虚引用
3.3 枚举
枚举类型是Java 5中新增特性的一部分,它是一种特殊的数据类型,之所以特殊是因为它既是一种类(class)类型却又比类类型多了些特殊的约束,但是这些约束的存在也造就了枚举类型的简洁性、安全性以及便捷性。
用法一:常量
package code0306;
enum eColor {
RED,GREEN,BLANK,YELLOW
}
public class testEnum {
public static void main(String[] args) {
// TODO Auto-generated method stub
eColor etest=eColor.RED;
System.out.println(etest);
for(eColor ec:eColor. values()){
//遍历颜色分量并输出声明顺序
System.out.println(ec+" ordinal "+ ec. ordinal());
}
}
}
//程序运行结果
RED
RED ordinal 0
GREEN ordinal 1
BLANK ordinal 2
YELLOW ordinal 3
用法二:switch
switch语句支持int,char,enum,String类型,使用枚举,能让我们的代码可读性更强。
class Trafficlight {
eColor color = eColor.RED;
public void change() {
switch (color) {
case RED:
color = eColor.GREEN;
break;
case YELLOW:
color = eColor.RED;
break;
case GREEN:
color = eColor.YELLOW;
break;
}
}
}
3.4 注解
java注解(@Annotation)是在JDK5时引入的特性,鉴于目前大部分框架(如 Junit、Struts、Spring)都使用了注解简化代码并提高编码的效率。
Java 语言中的类、方法、变量、参数和包等都可以被注解。和 Javadoc 不同,Java注解可以通过反射获取标注内容。
在编译器生成类文件时,注解可以被嵌入到字节码中。Java 虚拟机可以保留注解内容,在运行时可以获取到标注内容 。当然它也支持自定义 Java 标注。
1.作用在代码的常用注解是
@Override - 检查该方法是否是重载方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
@Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
@SuppressWarnings - 指示编译器去忽略注解中声明的警告。
这几个注解都具有编译检查作用
2.作用在其他注解的常用注解(或者说 元注解):
@Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
@Documented - 标记这些注解是否包含在用户文档中。
@Target - 标记这个注解应该是哪种 Java 成员。
@Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)