天天看点

Java程序设计-- 第3章 数组、引用、枚举和注解Java程序设计-- 第3章 数组、引用、枚举和注解

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 - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)