百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

JDK5.0新特性(jdk1.9新特性)

toyiye 2024-07-15 01:18 8 浏览 0 评论

1. JDK5特性

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

静态导入、自动装箱/拆箱、增强for循环、可变参数、枚举、泛型

1.1. 静态导入(了解)

JDK 1.5 增加的静态导入语法用于导入类的某个静态属性或方法。使用静态导入可以简化程序对类静态属性和方法的调用。

语法:

import static 包名.类名.静态属性|静态方法|*

例如:

import static java.lang.System.out

import static java.lang.Math.*

import static java.lang.System.out;

import static java.lang.Math.*;

public class Demo {

public static void main(String[] args) {

// 普通写法

System.out.println("hello world");

int max = Math.max(100, 200);

System.out.println(max);

// 静态导入

out.println("hello world");

int max2 = max(100, 200);

System.out.println(max2);

}

}


1.2. 增强for循环

引入增强for循环的原因:在JDK5以前的版本中,遍历数组或集合中的元素,需先获得数组的长度或集合的迭代器,比较麻烦!

因此JDK5中定义了一种新的语法——增强for循环,以简化此类操作。增强for循环只能用在数组、或实现Iterable接口的集合类

语法格式:

for(变量类型 变量 :需迭代的数组或集合){}


For each是为了让你的代码变得简捷、和容易维护。

它的速度也普通遍历的速度是一致的。

1.3. 可变参数

JDK中具有可变参数的类Arrays.asList()方法。

分别传多个参、传数组,传数组又传参的情况。

注意:传入基本数据类型数组的问题。

从JDK 5开始, Java 允许为方法定义长度可变的参数。

语法:数据类型…变量名。

可变长参数是Object[] 数组。(可变参数里存的是对象数组)

JDK中的典型应用:

Arrays.asList(T…a)是jdk中的典型应用。

需求:对若干个整数进行求和

public static int sum1(int a,int b ) {

return a+b;

}

若干个整数求和如何解决?

可以使用数组接收整数。

public static int sum1(int[] numbers) {

if (numbers == null) {

return 0;

}

if (numbers.length == 0) {

return 0;

}

int sum = 0;

for (int num : numbers) {

sum += num;

}

return sum;

}


可以使用可变参数

public static int sum2(int... numbers) {

if (numbers == null) {

System.out.println("可变参数的值为null");

return 0;

}

if (numbers.length == 0) {

System.out.println("可变参数的值的长度为0");

return 0;

}

int sum = 0;

for (int num : numbers) {

sum += num;

}

return sum;

}


可变参数的使用

public static void main(String[] args) {

// int result = sum1(new int[] { 1, 3, 5, 7, 9 });

// System.out.println(result);

// // 使用了可变参数,传一个数组进去

// int result = sum2(new int[] { 1, 3, 5, 7, 9 });

// System.out.println(result);

// 使用了可变参数,不必声明数组,简化书写

// int result = sum2(2, 4, 6, 8, 10);

// int result = sum2(1);

int result = sum2();

System.out.println(result);

}


可变参数的细节

声明:

在一个方法中,最多只能有一个可变参数。

可变参数只能放在参数列表的最后面。

调用:

当使用可变参数时,可以传0或多个参数。

当使用可变参数时,也可以传一个数组进去,就表示多个参数。

使用:

在方法内部使用时,就是在使用一个数组。

当调用时没有传参数时(传了0个),这时在方法内部的参数数组是有值的(不为null),但长度为0.


1.4. 自动装箱/拆箱

自动装箱:指开发人员可以把一个基本数据类型直接赋给对应的包装类

自动拆箱:指开发人员可以把一个包装类对象直接赋给对应的基本数据类型。

典型应用:

List list = new ArrayList();

list.add(1);

//list.add(new Integer(1));

int i=list.get(0);

//int j = (Integer)list.get(0);

1.4.1. 基本数据类型包装类

包装类 基本数据类型

Byte

byte

Short

short

Integer

int

Long

long

Boolean

boolean

Float

float

Double

double

Character

char

对象变基本数据类型:拆箱

基本数据类型包装为对象:装箱


为了使得java的基本类型有更多的功能,java为其所有的基本类型提供了包装类来封装常见的功能。如:最大值、数值转换等。

将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据

所属的包:java.lang.*


常见应用一:

获取最大最小值MAX_VALUE / MIN_VALUE

整数类型最大值

Integer.MAX_VALUE

System.out.println(Integer.MIN_VALUE);// -2147483648

System.out.println(Integer.MAX_VALUE);// 2147483647


应用二:

基本数据类型和字符串之间的转换

例:Integer的parseInt方法,intValue方法

基本数据类型转换成字符串:

1:基本数据类型+””

2:基本数据类型.toString(基本数据类型值);

例如 Integer.toString(34); //将34变成了”34”

基本数据类型转字符串

int i=100;

String str=100+"";

String string = Integer.toString(100);


字符串变基本数据类型

基本数据类型 a=基本数据类型包装类.parse基本数据类型(String str);

str="123";

int parseInt = Integer.parseInt(str);

System.out.println(parseInt);

注意:

public static int parseInt(String s)

Integer类中的parseInt方法是静态的 参数必须是数字格式


Double

str = "3.14";

double parseInt2 = Double.parseDouble(str);

System.out.println(parseInt2);

boolean b = Boolean.parseBoolean("true");


应用三:

进制转换:

十进制转成其他进制.

toBinaryString(int i)
以二进制(基数 2)无符号整数形式返回一个整数参数的字符串表示形式。

toHexString(int i)
以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式。

toOctalString(int i)
以八进制(基数 8)无符号整数形式返回一个整数参数的字符串表示形式。

那么其他进制转成十进制

parseInt(String radix);

parseInt(String s, int radix)
使用第二个参数指定的基数,将字符串参数解析为有符号的整数。


十进制转其他进制

// 十进制转二进制

String binaryString = Integer.toBinaryString(100);

System.out.println(binaryString); // 1100100

// 十进制转十六进制

String hexString = Integer.toHexString(100);

System.out.println(hexString); // 64


// 十进制转八进制

String octalString = Integer.toOctalString(100);

System.out.println(octalString); // 144


其他进制转十进制

// 字符串转对应的进制

int parseInt3 = Integer.parseInt(octalString);

System.out.println(parseInt3);

// 二进制转十进制

int parseInt4 = Integer.parseInt(binaryString, 2);

System.out.println(parseInt4);

// 十六进制转十进制

int parseInt5 = Integer.parseInt(hexString, 16);

System.out.println(parseInt5);

// 八进制转十进制

int parseInt6 = Integer.parseInt(octalString, 8);

System.out.println(parseInt6);


JDK5.0后出现了自动装箱和拆箱

JDK5.0以后,简化了定义方式。

Integer x = new Integer(5);//装箱

int intValue = x.intValue(); //拆箱


// 5.0简化书写

// 自动装箱。new Integer(5);

Integer y = 5;

// 对象加整数,x 进行了自动拆箱,变成了int 型 和5进行加法运算后再将和进行装箱赋给x。

y = y + 5; // 是通过Integer.intValue() 方法进行拆箱


练习:

public static void main(String[] args) {

Integer a = 127;

Integer b = 127;

System.out.println(a == b);


Integer c = 128;

Integer d = 128;

System.out.println(c == d);

}

请问结果?

a==b 为true 因为a和b指向了同一个Integer 对象.

Integer的缓存大小-128 ~127 之间也就是byte的范围。

1.5. 枚举类

有时候,变量的取值只是在一个有范围内,例如:服装的尺寸有小,中,大,和超大尺寸.我们可以将这些尺寸定义为定义变量并保存值为 1,2,3,4 或者S M L X ,这样可以解决问题.但是变量很有可能保存了一个错误的值(0 或者m)

一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,此类问题在JDK5以前采用自定义带有枚举功能的类解决,Java5以后可以直接使用枚举予以解决。

例如: 交通灯(红、黄、绿) 性别(男、女) 星期(星期一、二、三…..)

分数等级(A、B、C、D、E)

JDK 5新增的 enum 关键字用于定义一个枚举类。

枚举的实现

使用enum定义枚举类

在枚举类中定义枚举值(大写)

enum Gender {

MALE, FEMALE;

}

使用javap命令



发现其中每一个枚举值都是枚举类的具体实例对象.只不过是静态常量.

枚举类具有如下特性:

枚举类也是一种特殊形式的Java类。

枚举类中声明的每一个枚举值代表枚举类的一个实例对象。

与java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数.

public class Demo1 {

public static void main(String[] args) {

Gender male = Gender.MALE;

System.out.println(male.getInfo());

}

}


enum Gender {

MALE("男"), FEMALE;

// 成员变量

private String info;

// 构造函数

private Gender() {

}

private Gender(String info) {

this.info = info;

}

// 成员方法

public String getInfo() {

return info;

}

}

枚举类可以声明抽象方法,但是要有具体的枚举值去实现.

public class Demo1 {

public static void main(String[] args) {

Gender male = Gender.MALE;

System.out.println(male.getInfo());

male.speak();

}

}


enum Gender {

MALE("男") {

@Override

public void speak() {

System.out.println("是男人");

}

},

FEMALE {

@Override

public void speak() {

System.out.println("是女人");

}

};


// 成员变量

private String info;

// 构造函数

private Gender() {

}

private Gender(String info) {

this.info = info;

}

// 成员方法

public String getInfo() {

return info;

}

public abstract void speak();

}


枚举类也可以实现接口(序列化)、或继承抽象类。

JDK5中扩展了swith语句,它除了可以接收int, byte, char, short外,还可以接收一个枚举类型(enum)

public class Demo2 {

public static void main(String[] args) {

WeekDay mon = WeekDay.MON;

switch (mon) {

case MON:

System.out.println("星期一要上班...");

break;

case TUE:

System.out.println("星期二,继续上班...");

break;

}

}

}


enum WeekDay {

MON, TUE, WED, THU, FRI, SAT, SUN;

}


若枚举类只有一个枚举值,则可以当作单态设计模式使用。

练习:

请编写一个关于星期几的枚举WeekDay,要求:枚举值:Mon,Tue,Wed,Thu,Fri,Sat,Sun 该枚举要有一个方法,调用该方法返回中文格式的星期。

enum WeekDay {

MON {

@Override

public String getInfo() {

return "星期一";

}

},

TUE {

@Override

public String getInfo() {

return "星期二";

}

},

WED {

@Override

public String getInfo() {


return "星期三";

}

},

THU {

@Override

public String getInfo() {

return "星期四";

}

},

FRI {

@Override

public String getInfo() {

return "星期五";

}

},

SAT {

@Override

public String getInfo() {

return "星期六";

}

},

SUN {

@Override

public String getInfo() {

return "星期天";

}

};


public abstract String getInfo();

}


1.6. 泛型

泛型方法

需求:写一个函数,调用者传递什么类型的变量,该函数就返回什么类型的变量?

实现一:

由于无法确定具体传递什么类型的数据.那么方法的形参就定义为Object类型.返回值也就是Object类型.但是使用该函数时需要强制类型转换.

private Object getDate(Object obj) {

return obj;

}


当不进行强制类型转换能否写出该功能?


目前所学的知识无法解决该问题

就需要使用泛型类解决

使用的泛型的自定义来解决以上问题。

泛型: 就是将类型当作变量处理。规范泛型的定义一般是一个大写的任意字母。


1. 函数上的泛型定义

当函数中使用了一个不明确的数据类型,那么在函数上就可以进行泛型的定义。

public <泛型的声明> 返回值类型 函数名( 泛型 变量名 ){

}


public static void main(String[] args) {

int[] arr = { 1, 2, 3, 4, 5 };

new Demo6().getData(5);

}

public <T> T getData(T data) {

return data;

}


细节:

使用泛型方法前需要进行泛型声明,使用一对尖括号 <泛型>,声明的位置在static后返回值类型前。

当一个类中有多个函数声明了泛型,那么该泛型的声明可以声明在类上。

泛型类

格式

2. 类上的泛型声明

修饰符 class 类名<泛型>{

}


import java.util.Arrays;

public class Demo6<T> {

public static void main(String[] args) {

// 使用泛型类,创建对象的时候需要指定具体的类型

new Demo6<Integer>().getData(5);

}

public T getData(T data) {

return data;

}


// 反序任意类型数组

public void reverse(T[] arr) {

int start = 0;

int end = arr.length - 1;

for (int i = 0; i < arr.length; i++) {

if (start < end) {

T temp = arr[start];

arr[start] = arr[end];

arr[end] = temp;

}

}

}


在泛型类中定义一个静态方法

public class Demo6<T> {

public static void main(String[] args) {

System.out.println(getData2(100));

}


public T getData(T data) {

return data;

}


//静态方法

public static T getData2(T data) {

return data;

}

}



注意:静态方法不可以使用类中定义的泛型

因为类中的泛型需要在对象初始化时指定具体的类型,而静态优先于对象存在。那么类中的静态方法就需要单独进行泛型声明,声明泛型一定要写在static后,返回值类型之前

泛型类细节:

1、创建对象的时候要指定泛型的具体类型

2、创建对象时可以不指定泛型的具体类型(和创建集合对象一眼)。默认是Object,例如我们使用集合存储元素的时候没有使用泛型就是那么参数的类型就是Object

3、类上面声明的泛型只能应用于非静态成员函数,如果静态函数需要使用泛型,那么

需要在函数上独立声明。

4、如果建立对象后指定了泛型的具体类型,那么该对象操作方法时,这些方法只能操作一种数据类型。

5、所以既可以在类上的泛型声明,也可以在同时在该类的方法中声明泛型。


泛型练习:

定义泛型成员

public class Demo7 {

public static void main(String[] args) {

Father<String> f = new Father<String>("jack");

System.out.println(f.getT());

Father<Integer> f2 = new Father<Integer>(20);

System.out.println(f2.getT());

}

}


class Father<T> {

private T t;

public Father() {

}

public Father(T t) {

super();

this.t = t;

}


public T getT() {

return t;

}

public void setT(T t) {

this.t = t;

}

}


如果Father类有子类,子类该如何实现

public class Demo7 {

public static void main(String[] args) {

Father<String> f = new Father<String>("jack");

System.out.println(f.getT());

Father<Integer> f2 = new Father<Integer>(20);

System.out.println(f2.getT());

}

}


class Father<T> {

private T t;

public Father() {

}

public Father(T t) {

super();

this.t = t;

}


public T getT() {

return t;

}

public void setT(T t) {

this.t = t;

}

}

//子类指定了具体的类型

class Son extends Father<String>{

}

//子类也需要使用泛型

class Son3<T> extends Father<T>{

}

//错误写法,父类上定义有泛型需要进行处理

class Son2 extends Father<T>{

}


泛型接口

public class Demo8 {

public static void main(String[] args) {

MyInter<String> my = new MyInter<String>();

my.print("泛型");

MyInter2 my2 = new MyInter2();

my.print("只能传字符串");

}

}


interface Inter<T> {

void print(T t);

}


// 实现不知为何类型时可以这样定义

class MyInter<T> implements Inter<T> {

public void print(T t) {

System.out.println("myprint:" + t);

}

}

//使用接口时明确具体类型。

class MyInter2 implements Inter<String> {

@Override

public void print(String t) {

System.out.println("myprint:" + t);

}

}

泛型通配符

需求:

定义一个方法,接收一个集合对象(该集合有泛型),并打印出集合中的所有元素。

例如集合对象如下格式:

Collection<Person> coll = new ArrayList<Person>();

coll.add(new Person("jack", 20));

coll.add(new Person("rose", 18));

Collection<Object> coll2 = new ArrayList<Object>();

coll2.add(new Object());

coll2.add(new Object());

coll2.add(new Object());


Collection<String> coll3 = new ArrayList<String>();

coll3.add("abc");

coll3.add("ddd");

coll3.add("eee");


分析,集合对象中的元素的类型是变化的,方法的形参的那么泛型类型就只能定义为Object类型.

import java.util.ArrayList;

import java.util.Collection;

import java.util.HashSet;

import java.util.Iterator;

public class Demo9 {

public static void main(String[] args) {

ArrayList<Object> arr = new ArrayList<Object>();

arr.add(new Object());

arr.add("String");

print(arr);


//将集合的泛型设置类String类型,是Object子类

HashSet<String> hs = new HashSet<String>();

hs.add("hello");

hs.add("jack");

//由于print方法接收的集合进行了元素限定,只接受限定为Object类型的集合,编译不通过

//print(hs);

}


public static void print(Collection<Object> coll) {

Iterator<Object> it = coll.iterator();

while (it.hasNext()) {

Object next = it.next();

System.out.println(next);

}

}

}

但是,由于print方法接收的集合进行了元素限定,只接受限定为Object类型的集合,编译不通过该问题如何解决?

可以把方法的形参的泛型去掉,那么方法中就把集合中的元素当做Object类型处理.

也可以使用使用泛型通配符

public class Demo9 {

public static void main(String[] args) {

ArrayList<Object> arr = new ArrayList<Object>();

arr.add(new Object());

arr.add("String");

print(arr);

// 将集合的泛型设置类String类型,是Object子类

HashSet<String> hs = new HashSet<String>();

hs.add("hello");

hs.add("jack");

// 使用泛型通配符,编译通过。

print(hs);

}


public static void print(Collection<?> coll) {

Iterator<?> it = coll.iterator();

while (it.hasNext()) {

Object next = it.next();

System.out.println(next);

}

}

}


上述就使用了泛型通配符

通配符:?

public void show(List<?> list){

}

可以对类型进行限定范围。

?extends E: 接收E类型或者E的子类型。

? super E: 接收E类型或者E的父类型。


限定泛型通配符的边界

限定通配符的上边界:

extends

接收Number 类型或者Number的子类型

正确:Vector<? extends Number> x = new Vector<Integer>();

错误:Vector<? extends Number> x = new Vector<String>();


限定通配符的下边界

super

接收Integer 或者Integer的父类型

正确:Vector<? super Integer> x = new Vector<Number>();

错误:Vector<? super Integer> x = new Vector<Byte>();


总结:

JDK5中的泛型允许程序员在编写集合代码时,就限制集合的处理类型,从而把原来程序运行时可能发生问题,转变为编译时的问题,以此提高程序的可读性和稳定

注意:泛型是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛形的java程序后,生成的class文件中将不再带有泛形信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。

泛型的基本术语,以ArrayList<E>为例:<>念着typeof

ArrayList<E>中的E称为类型参数变量

ArrayList<Integer>中的Integer称为实际类型参数

整个称为ArrayList<E>泛型类型

整个ArrayList<Integer>称为参数化的类型ParameterizedType

相关推荐

「linux专栏」top命令用法详解,再也不怕看不懂top了

在linux系统中,我们经常使用到的一个命令就是top,它主要是用来显示系统运行中所有的进程和进程对应资源的使用等信息,所有的用户都可以使用top命令。top命令内容量丰富,可令使用者头疼的是无法全部...

Linux 中借助 perf 对 php 程序模拟CPU高的案例分析

导语本文是一篇Linux借助工具分析CPU高的优化案例,没有任何干货内容,很详细的展示了优化CPU高的具体步骤,非常适合初中级读者阅读!...

centos漏洞处理方法(centos podman)

centos服务器最近有诸多漏洞,修复命令及对应的漏洞整理后,分享给大家RHSA-2020:1176-低危:avahi安全更新yumupdateavahi-libsRHSA-2017:326...

Linux上的free命令详解(Buffer和Cache)

解释一下Linux上free命令的输出。下面是free的运行结果,一共有4行。为了方便说明,我加上了列号。这样可以把free的输出看成一个二维数组FO(FreeOutput)。例如:FO[2][1]...

linux 命令行之你真的会用吗?--free 基本用法篇

free命令行统计内存使用率及swap交换分区的使用率数据。是由sourceforge负责维护的,在ubuntu上其包名为procps,这个源码包中,除了free还有ps,top,vmstat,ki...

kong api gateway 初体验(konga github)

kongapigateway初体验(firstsight?)。Kong是一个可扩展的开源API层(也称为API网关或API中间件)。Kong运行在任何RESTfulAPI的前面,并通过插件...

在Ubuntu下开启IP转发的方法(ubuntu20 ip)

IP地址分为公有ip地址和私有ip地址,PublicAddress是由INIC(internetnetworkinformationcenter)负责的,这些IP地址分配给了注册并向INIC提...

基于 Kubernetes 的 Serverless PaaS 稳定性建设万字总结

作者:许成铭(竞霄)数字经济的今天,云计算俨然已经作为基础设施融入到人们的日常生活中,稳定性作为云产品的基本要求,研发人员的技术底线,其不仅仅是文档里承诺的几个九的SLA数字,更是与客户切身利益乃...

跟老韩学Ubuntu Linux系列-sysctl 帮助文档

sysctl一般用于基于内核级别的系统调优,man帮助手册如下。...

如何在 Linux/Unix/Windows 中发现隐藏的进程和端口

unhide是一个小巧的网络取证工具,能够发现那些借助rootkit、LKM及其它技术隐藏的进程和TCP/UDP端口。这个工具在Linux、UNIX类、MS-Windows等操作系统下都...

跟老韩学Ubuntu Server 2204-Linux性能管理-uptime指令帮助手册

uptime指令是每个从事Linux系统工作的相关同学必知必会的指令之一,如下是uptime指令的帮助手册。UPTIME(1)...

Openwrt+Rclone+emby+KODI搭建完美家庭影音服务器

特别声明:本篇内容参考了波仔分享,在此表示感谢!上一篇《Openwrt+emby+KODI搭建家庭影音服务器》只适用影音下载到本地的情形,不能播放云盘中的影音,内容较少,缺少了趣味性,也不直观。...

Linux Shell脚本经典案例(linux shell脚本例子)

编写Shell过程中注意事项:开头加解释器:#!/bin/bash语法缩进,使用四个空格;多加注释说明。命名建议规则:变量名大写、局部变量小写,函数名小写,名字体现出实际作用。默认变量是全局的,在函数...

解决 Linux 性能瓶颈的黄金 60 秒

如果你的Linux服务器突然负载暴增,告警短信快发爆你的手机,如何在最短时间内找出Linux性能问题所在?来看Netflix性能工程团队的这篇博文,看它们通过十条命令在一分钟内对机器性能问题进行诊断。...

跟老韩学Ubuntu Server 2204-Linux性能管理-vmstat指令帮助手册

vmstat可查看ubuntlinux的综合性能,是每个从事Linux人员必知必会、需掌握的核心指令之一。vmstat指令帮助手册如下。VMSTAT(8)...

取消回复欢迎 发表评论:

请填写验证码