javaweb-day03-1&2(基础加强 - 静态导入、自动装箱/拆箱、增强for循环、可变参数、枚举)

时间:2023-02-18 12:16:50

JDK 5.0 新特性

JDK5中新增了很多新的java特性,利用这些新语法可以帮助开发人员编写出更加高效、清晰,安全的代码。

  • 静态导入
  • 自动装箱/拆箱
  • 增强for循环
  • 可变参数
  • 枚举
  • 反射
  • 内省
  • 泛型
  • 元数据

 

静态导入

普通导入是导入某个类,静态导入是导入某个类的 静态方法 静态属性

为了简化书写,但不常用。

  • 语法:
    • import static 包名.类名.静态属性|静态方法|*
  • 例如:
    • import static java.lang.System.out
    • import static java.lang.Math.*

package cn.mengmei.import_static;

import static java.lang.System.out;
import static java.util.Arrays.*;

public class Demo1 {

public static void main(String[] args) {

out.println("hello world");

System.out.println( asList(new Integer[] { 1, 2, 3, 4 }) );
}

}
运行结果:

hello world
[1, 2, 3, 4]



自动装箱/拆箱

  •   JDK5.0的语法允许把一个基本数据类型直接赋给对应的包装类变量, 或者赋给Object 类型的变量,这个过程称之为自动装箱。
  •   自动拆箱与自动装箱正好相反,即把包装类对象直接赋给一个对应的基本类型变量。
  •   典型应用:
    • List  list = new ArrayList();
    • list.add(1);
    • int  j = (Integer)list.get(0);

package cn.mengmei.demo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Demo2 {

public static void main(String[] args) {

//5.0 jvm
Integer i = 1; //自动装箱
int j = i; //自动拆箱

//典型应用
List list = new ArrayList();
list.add(1); //自动装箱
list.add(2);
list.add(3);

Iterator it = list.iterator();
while(it.hasNext()){
int k = (Integer)it.next(); //自动拆箱
}
}

}


增强for循环

  •   引入增强for循环的原因:在JDK5以前的版本中,遍历数组或集合中的元素,需先获得数组的长度或集合的迭代器,比较麻烦!
  •   因此JDK5中定义了一种新的语法——增强for循环,以简化此类操作。增强for循环只能用在数组、或实现Iterable接口的集合类上
  •   语法格式:                                             
    • for(变量类型 变量 :需迭代的数组或集合){
    •  
    • }
  •   使用增强for循环的几个注意事项 (以下程序的输出结果?)
    • int arr[] = new int[5];
    • for(int num : arr){
    •     num = 1;
    • }
    • System.out.println(arr[0]);  //0
    •  

    • List<String> list = new ArrayList<String>();
    • list.add("xxx");
    • for(String str : list){
    •        str = "yyy";
    • }
    • System.out.println(list.get(0));  //xxx

package cn.mengmei.demo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.junit.Test;

public class Demo3 {

//注意:增强for循环只适合取数据,不要想着用它给数组赋值。

@Test
public void test1() {
int[] arr = new int[5];
for(int a : arr){
a = 1; //只是把变量a的值改了,并没有改数组里面的值。
}
System.out.println(arr[0]);
}

@Test
public void test2() {
List<String> list = new ArrayList<String>();
list.add("xxx");
for(String a : list){ //定义了个变量去指向迭代出来的东西。
a = "yyy"; //只是将这个变量的指向改变了,原来指向"xxx",现在指向"yyy",并没有改变集合中的东西。
}
System.out.println(list.get(0));
}

@Test
public void test3() {
int[] arr = new int[]{1,2,3};
for(int a : arr){
System.out.println(a);
}
}

@Test
public void test4() {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
for(int a : list){
System.out.println(a);
}
}

@Test
public void test5() {
Map<Integer,String> map = new LinkedHashMap<Integer,String>();
map.put(1, "aa");
map.put(2, "bb");
map.put(3, "cc");

//传统方式一:
Set<Integer> keySet = map.keySet();
Iterator<Integer> it = keySet.iterator();
while(it.hasNext()){
int key = it.next();
String value = map.get(key);
System.out.println(key+":"+value);
}

//高级for循环一:
for(int key : map.keySet()){
String value = map.get(key);
System.out.println(key+"::"+value);
}


//传统方式二:
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
Iterator<Map.Entry<Integer, String>> it2 = entrySet.iterator();
while(it2.hasNext()){
Map.Entry<Integer, String> me = it2.next();
int key = me.getKey();
String value = me.getValue();
System.out.println(key+":::"+value);
}

//高级for循环二:
for(Map.Entry<Integer, String> me : map.entrySet()){
int key = me.getKey();
String value = me.getValue();
System.out.println(key+"::::"+value);
}
}

}


可变参数

  • 测试JDK中具有可变参数的类Arrays.asList()方法。分别传多个参、传数组,传数组又传参的情况。
    • 注意:传入基本数据类型数组的问题。
  • 从JDK 5开始, Java 允许为方法定义长度可变的参数。语法:
    • public void foo(int … args){
    • }
  • 注意事项:
    • 调用可变参数的方法时, 编译器将自动创建一个数组保存传递给方法的可变参数,因此,程序员可以在方法体中以数组的形式访问可变参数
    • 可变参数只能处于参数列表的最后, 所以一个方法最多只能有一个长度可变的参数

 

package cn.mengmei;

import java.util.Arrays;
import java.util.List;

public class Demo1 {

public static void main(String[] args) {

sum(1,2,3,4,5);

Integer[] arr = {1,2,3,4,5};
sum(arr); //如果一个函数接受可变参数,那么往里面传数组也是可以的。

List list = Arrays.asList(1,2,3);
System.out.println(list);

Integer[] arr1 = {1,2,3,4,5};
list = Arrays.asList(arr1); //5
System.out.println(list);

//注意
int[] arr2 = {1,2,3,4,5};
list = Arrays.asList(arr2); //1
System.out.println(list);

//总结:以后能用对象类型,就不用基本数据类型。

sum2(1,2,3,4,5);
}

public static void sum(Integer...args){
int sum = 0;
for(int arg : args){
sum += arg;
}

System.out.println(sum);
}

//注意:可变参数必须处于参数列表的最后,且一个方法只能拥有一个可变参数。
public static void sum2(Integer num, Integer...args){
int sum = 0;
for(int arg : args){
sum += arg;
}
sum += num;

System.out.println(sum);
}

}

枚举类

  • 为什么需要枚举?
    • 一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,此类问题在JDK5以前采用自定义带有枚举功能的类解决,Java5以后可以直接使用枚举予以解决。
  • JDK 5新增的 enum 关键字用于定义一个枚举类。
  • 枚举类具有如下特性:
    • 枚举类也是一种特殊形式的Java类。
    • 枚举类中声明的每一个枚举值代表枚举类的一个实例对象。
    • 与java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数,但枚举类的构造函数必须为私有的(这点不难理解)。
    • 枚举类也可以实现接口、或继承抽象类。
    • JDK5中扩展了swith语句,它除了可以接收int, byte, char, short外,还可以接收一个枚举类型。
    • 若枚举类只有一个枚举值,则可以当作单态设计模式使用。
  • 练习:请编写一个关于星期几的枚举WeekDay,要求:
    • 枚举值:Mon,Tue,Wed,Thu,Fri,Sat,Sun
    • 该枚举要有一个方法,调用该方法返回中文格式的星期。
  • Java中声明的枚举类,均是java.lang.Enum类的孩子,它继承了Enum类的所有方法。常用方法:
    • name()         //枚举对象的名称
    • ordinal()       //枚举对象在声明中的位置序数。
    • valueof(Class enumClass, String name)        //将字符串转化成枚举对象。
    • values()      //此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值非常方便。

package cn.mengmei;

public class Demo2 {

public static void main(String[] args) {

WeekDay.Mon.printName(); //星期一
WeekDay.Mon.toLocalString(); //Monday

String name = "Wed";
WeekDay w = WeekDay.valueOf(WeekDay.class, name); //将一个字符串转化成一个枚举对象
System.out.println(w.ordinal()); //2,初始常量序数为0

//遍历枚举类中的对象
WeekDay[] days = WeekDay.values();
for(WeekDay day : days){
System.out.println(day);
}
}

}

//一个拥有属性和抽象方法的的枚举类:
enum WeekDay {
Mon("星期一"){
@Override
public void toLocalString() {
// TODO Auto-generated method stub
System.out.println("Monday");
}
},Tue("星期二"){
@Override
public void toLocalString() {
// TODO Auto-generated method stub
System.out.println("Tuesday");
}
},Wed("星期三"){
@Override
public void toLocalString() {
// TODO Auto-generated method stub
System.out.println("Wednesday");
}
},Thu("星期四"){
@Override
public void toLocalString() {
// TODO Auto-generated method stub
System.out.println("Thursday");
}
},
Fri("星期五"){
@Override
public void toLocalString() {
// TODO Auto-generated method stub
System.out.println("Friday");
}
},Sat("星期六"){
@Override
public void toLocalString() {
// TODO Auto-generated method stub
System.out.println("Saturday");
}
},Sun("星期日"){
@Override
public void toLocalString() {
// TODO Auto-generated method stub
System.out.println("Sunday");
}
};

private WeekDay(String name){
this.cname = name;
}

private String cname;

public void printName(){
System.out.println(this.cname);
}

//抽象类:每个对象都必须单独实现
public abstract void toLocalString();

}

枚举不能继承类,因为它本身就继承了一个Enum类。

但是枚举可以实现接口。