前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java5新特性及使用

Java5新特性及使用

作者头像
Abalone
发布于 2022-07-14 06:23:07
发布于 2022-07-14 06:23:07
1.4K00
代码可运行
举报
文章被收录于专栏:影像技术栈影像技术栈
运行总次数:0
代码可运行

新特性列表

一、泛型(Generics)

1. 概述

Java语言引入泛型的好处是安全简单。可以将运行时错误提前到编译时错误。在Java5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的任意化任意化带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。

泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法中,分别称为泛型类、泛型接口、泛型方法。

2. 泛型类、泛型接口

泛型类中的类型参数几乎可以用于任何可以使用接口名、类名的地方。以下是Jdk中Map接口的定义:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface Map<K,V> {

    V get(Object key);

    V put(K key, V value);

}

当声明或者实例化一个泛型的对象时,必须指定类型参数的值:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Map<Integer, String> map = new HashMap<Integer, String>();

对于常见的泛型模式,推荐的名称是:

  • K: 键
  • V: 值
  • E: 异常类
  • T: 泛型

3. 泛型方法

(1). 定义泛型方法

泛型方法使得该方法能独立于类而产生变化。以下是一个基本的指导原则:无论何时,只要你能做到,你就应该尽量使用泛型方法。也就是说,如果使用泛型方法可以取代将整个类泛型化,那么就应该只使用泛型方法,因为它可以使事情更清楚明白。要定义泛型方法,只需将泛型参数列表置于返回值之前,就像下面这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class GenericMethods {

    //当方法操作的引用数据类型不确定的时候,可以将泛型定义在方法上
    public <T> void f(T x){
        System.out.println(x.getClass().getName());
    }

    public static void main(String[] args) {
        GenericMethods gm = new GenericMethods();
        gm.f(99);
        gm.f("abc");
    }

}
(2). 可变参数泛型方法

泛型方法与可变参数列表能很好地共存。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class GenericVarargs {

    public static <T> List<T> makeList(T... args) {
        List<T> result = new ArrayList<T>();
        for(T item:args) {
            result.add(item);
        }
        return result;
    }

    public static void main(String[] args) {
        List ls = makeList("A");
        System.out.println(ls);
        ls = makeList("A","B","C");
        System.out.println(ls);
        ls = makeList("ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""));
        System.out.println(ls);
    }

}

:静态方法无法访问类上定义的泛型。如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上。

4. 泛型擦除

看以下一段代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ErasedTypeEquivalence {

    public static void main(String[] args) {
        Class c1 = new ArrayList<String>().getClass();
        Class c2 = new ArrayList<Integer>().getClass();
        System.out.println(c1 == c2); // 输出true.
    }

}

从以上代码的执行结果可以知道,ArrayList<String>ArrayList<Integer>是相同的类型。Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,成功编译过后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。

要想在表达式中使用类型,需要显式地传递类型的class对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Building {

}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class House extends Building {

}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ClassTypeCapture<T> {

    Class<T> kind;

    public ClassTypeCapture(Class<T> kind) {
        this.kind = kind;
    }

    public boolean f(Object arg) {
        return kind.isInstance(arg);
    }

    public static void main(String[] args) {
        ClassTypeCapture<Building> ctt1 = new ClassTypeCapture<Building>(Building.class);
        System.out.println(ctt1.f(new Building())); // true
        System.out.println(ctt1.f(new House())); // true
        ClassTypeCapture<House> ctt2 = new ClassTypeCapture<House>(House.class);
        System.out.println(ctt2.f(new Building())); // false
        System.out.println(ctt2.f(new House())); // true
    }
}

5. 通配符及泛型边界

  • 通配符(?): 当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用?通配符来表未知类型。例如:Class<?> classType = Class.forName("java.lang.String");
  • 上界(? extends T): 可以接收T类型或者其子类型的对象。
  • 下界(? super E): 可以接收T类型或者其父类型的对象。

6. 泛型总结

  • 泛型的类型参数只能是类类型,不能是基本数据类型。
  • 泛型的类型参数可以有多个。
  • 所有泛型类的类型参数在编译时都会被擦除。
  • 创建泛型对象时请指明类型,让编译器尽早的做参数检查。
  • 不能创建泛型数组。如果想要创建泛型数组,建议使用ArrayList
  • 使用带泛型的类创建对象时,等式两边指定的泛型必须一致。
  • 泛型的好处:
    • 类型安全。
    • 消除强制类型转换。
    • 提高性能。

二、增强for循环(Enhanced for Loop)

在Java5中,引入了另一种形式的for循环来对集合、数组、Map等进行遍历。如以下示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int[] integers = {1, 2, 3, 4};
/* 开始遍历 */
for (int i : integers) {
    System.out.println(i);/* 依次输出“1”、“2”、“3”、“4” */
}

借助增强for循环,可以用一种更简单地方式来完成遍历。能用这种方法遍历的对象的类型,可以是数组、CollectionMap或者任何其它实现了java.lang.Iterable接口的类。通过跟同样是在Java5中引入的泛型机制配合使用,可以精确的控制能采用的循环变量的类型。而且,因为这么编写的代码,会在编译期间被自动当成是和传统写法相同的形式,所以不必担心要额外付出性能方面的代价。

:Java采用for(而不是意义更明确的foreach)来引导这种一般被叫做for-each循环的循环,并使用:(而不是意义更明确的in)来分割循环变量名称和要被遍历的对象。这样做的主要原因,是为了避免因为引入新的关键字,造成兼容性方面的问题——在Java语言中,不允许把关键字当作变量名来使用,虽然使用foreach这名字的情况并不是非常多,但是in却是一个经常用来表示输入流的名字(例如java.lang.System类里,就有一个名字叫做instatic属性,表示标准输入流)。

三、自动装箱拆箱(Autoboxing/Unboxing)

1. 概述

自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。原始类型byte, short, char, int, long, float, doubleboolean对应的封装类分别为Byte, Short, Character, Integer, Long, Float, Double, Boolean

自动装箱时编译器调用valueOf将原始类型值转换成对象,同时自动拆箱时,编译器通过调用类似intValue(), doubleValue()这类的方法将对象转换成原始类型值。自动装箱和拆箱在Java中很常见,比如我们有一个方法,接受一个对象类型的参数,如果我们传递一个原始类型值,那么Java会自动将这个原始类型值转换成与之对应的对象。最经典的一个场景就是当我们向ArrayList这样的容器中增加原始类型数据时,就会发生自动装箱。代码示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ArrayList<Integer> intList = new ArrayList<Integer>();
intList.add(1); //自动装箱
intList.add(2); // 自动装箱

int number = intList.get(0); // 自动拆箱

2. 对象相等的比较

这是一个比较容易出错的地方,==可以用于原始值进行比较,也可以用于对象进行比较,当用于对象与对象之间比较时,比较的不是对象代表的值,而是检查两个对象是否是同一对象,这个比较过程中没有自动装箱发生。进行对象值比较不应该使用==,而应该使用对象对应的equals方法。看一个能说明问题的例子。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class AutoboxingTest {

    public static void main(String args[]) {
        // 示例 1: 使用'=='号进行原始类型的比较(没有自动装箱)
        int i1 = 1;
        int i2 = 1;
        System.out.println("i1==i2 : " + (i1 == i2)); // true

        // 示例 2: 使用'=='号进行原始类型和对象类型混合的比较(自动装箱)
        Integer num1 = 1;
        int num2 = 1;
        System.out.println("num1 == num2 : " + (num1 == num2)); // true

        // 示例 3: 使用'=='号进行Integer对象类型的比较(会有缓存的特殊情况)
        Integer obj1 = 127; // 自动装箱将调用`Integer.valueOf()`且缓存该对象,以便重用
        Integer obj2 = 127; // 获取已经缓存过的对象
        System.out.println("obj1 == obj2 : " + (obj1 == obj2)); // true

       // 示例 4: 使用'=='号进行Integer对象类型的比较(不会缓存)
        Integer obj3 = 128; // 自动装箱将调用`Integer.valueOf()`不缓存该对象
        Integer obj4 = 128; // 同样是自动装箱将调用`Integer.valueOf()`
        System.out.println("obj3 == obj4 : " + (obj3 == obj4)); // false

        // 示例 5: 使用'=='号进行`new`出来的新`Integer`对象类型的比较
        Integer one = new Integer(1); // no autoboxing
        Integer anotherOne = new Integer(1);
        System.out.println("one == anotherOne : " + (one == anotherOne)); // false
    }

}

3. 缓存部分对象

输出结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
i1==i2 : true
num1 == num2 : true
obj1 == obj2 : true
obj3 == obj4 : false
one == anotherOne : false

在 Java5 中,为Integer的操作引入了一个新的特性,会对-128127Integer对象进行缓存,当创建新的Integer对象时,如果符合这个这个范围,并且已有存在的相同值的对象,则返回这个对象,否则创建新的Integer对象。这种Integer缓存策略仅在自动装箱(autoboxing)的时候有用,使用构造器创建的Integer对象不能被缓存。

Integer类中有一个专门的私有静态内部类IntegerCache来负责Integer的缓存。代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * Cache to support the object identity semantics of autoboxing for values between
 * -128 and 127 (inclusive) as required by JLS.
 *
 * The cache is initialized on first usage.  The size of the cache
 * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
 * During VM initialization, java.lang.Integer.IntegerCache.high property
 * may be set and saved in the private system properties in the
 * sun.misc.VM class.
 */
private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            try {
                int i = parseInt(integerCacheHighPropValue);
                i = Math.max(i, 127);
                // Maximum array size is Integer.MAX_VALUE
                h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);

        // range [-128, 127] must be interned (JLS7 5.1.7)
        assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
}

Javadoc详细的说明这个类是用来实现缓存支持,并支持-128127之间的自动装箱过程。最大值127可以通过JVM的启动参数-XX:AutoBoxCacheMax=size修改。 缓存通过一个for循环实现。从小到大的创建尽可能多的整数并存储在一个名为cache的整数数组中。这个缓存会在Integer类第一次被使用的时候被初始化出来。以后,就可以使用缓存中包含的实例对象,而不是创建一个新的实例(在自动装箱的情况下)。

这种缓存行为不仅适用于Integer对象。我们针对所有整数类型的类都有类似的缓存机制。

  • ByteCache用于缓存Byte对象
  • ShortCache用于缓存Short对象
  • LongCache用于缓存Long对象
  • CharacterCache用于缓存Character对象

ByteShortLong有固定范围:-128127。对于Character, 范围是0127。除了Integer可以通过参数改变范围外,其它的都不行。

:在Java中另一个节省内存的例子就是字符串常量池

4. 自动装箱拆箱的隐患

另一个需要避免的问题就是混乱使用对象和原始数据值,一个具体的例子就是当我们在一个原始数据值与一个对象进行比较时,如果这个对象没有进行初始化或者为null,在自动拆箱过程中obj.xxxValue,会抛出NullPointerException,如下面的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static Integer count;

//NullPointerException on unboxing
if (count <= 0) {
    System.out.println("Count is not started yet");
}

因为自动装箱会隐式地创建对象,像前面提到的那样,如果在一个循环体中,会创建无用的中间对象,这样会增加GC压力,拉低程序的性能。所以在写循环时一定要注意代码,避免引入不必要的自动装箱操作。

四、枚举(Enums)

枚举(enum全称为enumeration)类型是 Java5 新增的类型,存放在java.lang包中,允许用常量来表示特定的数据片断,而且全部都以类型安全的形式来表示。

关于枚举的介绍,这里就不再细讲了,请参考我以前所整理的Java 枚举知识整理一文。

五、可变参数(Varargs)

1. 基本使用

在 Java5 中提供了可变参数(Varargs),也就是在方法定义中可以使用个数不确定的参数,对于同一方法可以使用不同个数的参数调用,例如print("hello");print("hello","lisi");等。下面介绍如何定义可变长参数以及如何使用可变长参数。

使用...表示可变长参数,例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
print(String... args) {
   // 方法代码
}

在具有可变长参数的方法中可以把参数当成数组使用,例如可以循环输出所有的参数值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
print(String... args) {
    for(String temp:args) {
        System.out.println(temp);
    }
}

调用的时候可以给出任意多个参数也可不给参数,例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
print();
print("hello");
print("hello","lisi");

2. 可变参数的使用规则

  • 拥有可变参数的方法可以被重载,在调用方法的时候,如果能够和固定参数的方法匹配,也能够与可变参数的方法匹配,则执行时会选择固定参数的方法。
  • 如果要调用的方法可以和两个可变参数匹配,则编译不会通过。
  • 一个方法只能有一个可变参数,并且这个可变参数必须是该方法的最后一个参数。
  • 可变参数可以兼容数组参数,但数组参数无法兼容可变参数。即在方法中定义可变参数后,我们可以像操作数组一样操作该参数;

3. 可变参数的使用规范

  • 避免带有可变参数的方法重载,容易让人陷入调用的陷阱及误区。
  • 别让null值和空值威胁到可变参数的方法。
  • 覆写可变参数方法也要满足以下的条件:
    • 重写方法不能缩小访问权限。
    • 参数列表必须与被重写方法相同(包括显示形式)。
    • 返回类型必须与被重写方法的相同或是其子类。
    • 重写方法不能抛出新的异常,或者超过了父类范围的异常,但是可以抛出更少、更有限的异常,或者不抛出异常。

六、静态导入(Static Import)

import static,即静态导入是JDK5中的新特性。一般我们导入一个类都用import com.xxx.ClassName;,而静态导入是这样的:import static com.xxx.ClassName.*;。这里多了个static,还有就是类名ClassName后面多了个.*,意思是导入这个类里的所有静态方法。当然,也可以只导入某个静态方法,只要把.*换成具体的静态方法名就行了。然后在这个类中,就可以直接用方法名调用静态方法,而不必用ClassName.方法名的方式来调用。

静态导入之前的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
double r = Math.cos(Math.PI * theta);

使用静态导入之后的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import static java.lang.Math.*;

double r = cos(PI * theta);

当你需要频繁访问一个或两个类的静态成员、静态方法时才使用静态导入。如果您过度的使用了静态导入功能,则可能导致您的程序无法读取且无法维护,从而导致您导入的所有静态成员和方法污染其名称空间。你的代码读者(包括你,在你写了几个月后)不会知道静态成员来自哪个类。从类中导入所有静态成员对可读性尤其有害,如果您只需要一个或两个成员,请单独导入它们。使用适当的,静态导入可以使您的程序更具可读性,通过删除重复的类名称,来减少样板代码。

七、注解(Annotations)

关于注解的介绍,这里就不再细讲了,请参考我前段时间所写的Java注解的理解和应用一文。

八、值得关注

1. 新增ProcessBuilder类

ProcessBuilder类是Java5在java.lang包中新添加的一个新类,此类用于创建操作系统进程,它提供一种启动和管理进程(也就是应用程序)的方法。在此之前,都是由Process类处来实现进程的控制管理。每个ProcessBuilder实例管理一个进程属性集。它的start()方法利用这些属性创建一个新的Process实例。start()方法可以从同一实例重复调用,以利用相同的或相关的属性创建新的子进程。

ProcessBuilder是一个final类,有两个带参数的构造方法,你可以通过构造方法来直接创建ProcessBuilder的对象。而Process是一个抽象类,一般都通过Runtime.exec()ProcessBuilder.start()来间接创建其实例。ProcessBuilder为进程提供了更多的控制,例如,可以设置当前工作目录,还可以改变环境参数。而Process类的功能相对来说简单的多。ProcessBuilder类不是同步的。如果多个线程同时访问一个ProcessBuilder,而其中至少一个线程从结构上修改了其中一个属性,它必须保持外部同步。

若要使用ProcessBuilder创建一个进程,只需要创建ProcessBuilder的一个实例,指定该进程的名称和所需参数。要执行此程序,调用该实例上的start()即可。下面是一个执行打开Windows记事本的例子。注意它将要编辑的文件名指定为一个参数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class PBDemo {

    public static void main(String args[]) {
        try {
            ProcessBuilder proc = new ProcessBuilder("notepad.exe", "testfile");
            proc.start();
        } catch (Exception e) {
            System.out.println("Error executing notepad.");
        }
    }

}

2. 新增Formatter格式化器(Formatter)

Formatter类是Java5中新增的printf-style格式化字符串的解释器,它提供对布局和对齐的支持,提供了对数字,字符串和日期/时间数据的常用格式以及特定于语言环境的输出。常见的Java类型,如bytejava.math.BigDecimaljava.util.Calendar都支持。 通过java.util.Formattable接口提供了针对任意用户类型的有限格式定制。

更详细的介绍见这里。主要使用方法的代码示例如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.io.BufferedReader;
import java.io.FileReader;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 格式化测试使用的示例类.
 *
 * @author blinkfox on 2017-11-28.
 */
public class FormatTester {

    private static final Logger log = LoggerFactory.getLogger(FormatTester.class);

    /**
     * 格式化.
     */
    private static void formatter() {
        StringBuilder sb = new StringBuilder();
        Formatter formatter = new Formatter(sb, Locale.US);

        // 可重新排序输出.
        formatter.format("%n%4$2s %3$2s %2$2s %1$2s %n", "a", "b", "c", "d"); // -> " d  c  b  a"
        formatter.format(Locale.FRANCE, "e = %+10.4f", Math.E); // -> "e =    +2,7183"
        formatter.format("%nAmount gained or lost since last statement: $ %(,.2f", 6217.58);
        // -> "Amount gained or lost since last statement: $ 6,217.58"

        log.info("打印出格式化后的字符串:{}", formatter);
        formatter.close();
    }

    /**
     * printf打印.
     */
    private static void printf() {
        String filename = "testfile";
        try (FileReader fileReader = new FileReader(filename)) {
            BufferedReader reader = new BufferedReader(fileReader);
            String line;
            int i = 1;
            while ((line = reader.readLine()) != null) {
                System.out.printf("Line %d: %s%n", i++, line);
            }
        } catch (Exception e) {
            System.err.printf("Unable to open file named '%s': %s", filename, e.getMessage());
        }
    }

    /**
     * stringFormat使用.
     */
    private static void stringFormat() {
        // 格式化日期.
        Calendar c = new GregorianCalendar(1995, Calendar.MAY, 23);
        String s = String.format("Duke's Birthday: %1$tm %1$te,%1$tY", c);
        // -> s == "Duke's Birthday: May 23, 1995"
        log.info(s);
    }

    /**
     * 格式化消息.
     */
    private static void messageFormat() {
        String msg = "欢迎光临,当前({0})等待的业务受理的顾客有{1}位,请排号办理业务!";
        MessageFormat mf = new MessageFormat(msg);
        String fmsg = mf.format(new Object[]{new Date(), 35});
        log.info(fmsg);
    }

    /**
     * 格式化日期.
     */
    private static void dateFormat() {
        String str = "2010-1-10 17:39:21";
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        try {
            log.info("格式化后的日期:{}", format.format(format.parse(str)));
        } catch (Exception e) {
            log.error("日期格式化出错!", e);
        }
    }

    public static void main(String[] args) {
        formatter();
        stringFormat();
        messageFormat();
        dateFormat();
        printf();
    }

}

3. 新增Scanner类(Scanner)

java.util.Scanner是Java5的新特征,主要功能是简化文本扫描,但这个类最实用的地方还是在获取控制台输入。

(1). Scanner概述

可以从字符串(Readable)、输入流、文件、Channel等来直接构造Scanner对象,有了Scanner了,就可以逐段(根据正则分隔式)来扫描整个文本,并对扫描后的结果做想要的处理。

Scanner默认使用空格作为分割符来分隔文本,但允许你使用useDelimiter(Pattern pattern)useDelimiter(String pattern)方法来指定新的分隔符。

主要API如下:

  • delimiter(): 返回此Scanner当前正在用于匹配分隔符的Pattern
  • hasNext(): 判断扫描器中当前扫描位置后是否还存在下一段。
  • hasNextLine(): 如果在此扫描器的输入中存在另一行,则返回true。
  • next(): 查找并返回来自此扫描器的下一个完整标记。
  • nextLine(): 此扫描器执行当前行,并返回跳过的输入信息。
(2). 扫描控制台输入

当通过new Scanner(System.in)创建了一个Scanner实例时,控制台会一直等待输入,直到敲回车键结束,把所输入的内容传给Scanner,作为扫描对象。如果要获取输入的内容,则只需要调用ScannernextLine()方法即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
* 扫描控制台输入.
*
* @author blinkfox 2017-11-28
*/
public class ScannerTest {

    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        System.out.println("请输入字符串:");
        while (true) {
            String line = s.nextLine();
            if (line.equals("exit")) break;
            System.out.println(">>>" + line);
        }
    }

}
(3).其它示例

该示例中会从myNumbers文件中读取长整型long的数据。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Scanner sc = new Scanner(new File("myNumbers"));
while (sc.hasNextLong()) {
    long aLong = sc.nextLong();
}

以下示例可以使用除空格之外的分隔符来从一个字符串中读取几个条目:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
String input = "1 fish 2 fish red fish blue fish";
Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
System.out.println(s.nextInt());
System.out.println(s.nextInt());
System.out.println(s.next());
System.out.println(s.next());
s.close();

将输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1
2
red
blue

4. 增强反射功能(Reflection)

Java5反射功能方面的增强主要在java.lang.Classjava.lang.reflect类中。

主要有以下内容增强:

  • 支持泛型: 可以检查类型、方法、构造方法或字段的声明并获取泛型所对应的类型信息。
  • 支持注解: 通过使用getAnnotation()方法获取已经在运行时标记为可用的方法和构造方法的类型,方法,字段,构造方法和形式参数的注释。人们还可以确定一个接口是否是一个注解类型。
  • 支持枚举: 可以确定一个类是否是一个枚举,以及一个字段是否代表一个枚举常量。
  • 支持可变参数: 可以确定一个方法或构造方法是否是可变参数方法。
  • 便利的方法: 用于确定一个类是否是本地的、匿名的还是成员类,以及一个类型的简单名称是什么。
  • java.lang.Class类型标记: 允许使用java.lang.Class的实例作为类型标记。

5. 增强集合框架(Collections Framework)

在Java5中集合框架的增强主要在以下几个方面:

  • 三种新语言特性都有针对集合,包括泛型增强for循环自动装箱
  • 三个新的接口已被添加到集合框架中,分别是:QueueBlockingQueueConcurrentMap(后两个位于java.util.concurrent包中)。
  • 提供了两个新的具体队列实现(PriorityQueueConcurrentLinkedQueue),一个现有的列表实现已经被改造来实现队列(LinkedList),并且提供了一个抽象队列实现(AbstractQueue)。
  • 已经添加了五个阻塞队列实现,以及一个ConcurrentMap实现,分别是:ArrayBlockingQueue, LinkedBlockingQueue, PriorityBlockingQueue, DelayQueue, SynchronousQueueConcurrentHashMap
  • 为类型安全的枚举提供了特殊用途的Map和Set实现。(EnumMapEnumSet)
  • 添加了特殊用途的copy-on-writeList和Set实现,分别是:CopyOnWriteArrayListCopyOnWriteArraySet
  • 提供了包装器的实现来对大多数Collection接口添加动态类型安全性的检查(Collections.checkedInterface)。检查要添加的元素的类型并返回结果。任何尝试添加非法类型的变量都会抛出一个ClassCastException异常。这个功能可以防止在运行的时候出错。
  • 提供了几个新的算法来处理集合。
    • frequency(Collection<?> c, Object o) - 计算指定集合中指定元素出现的次数。
    • disjoint(Collection<?> c1, Collection<?> c2) - 判断两个集合是否不相交,换句话说,是否它们不包含任何共同的元素。
    • addAll(Collection<? super T> c, T... a) - 将指定数组中的所有元素添加到指定的集合中。
    • Comparator<T> reverseOrder(Comparator<T> cmp) - 返回一个比较器,表示指定比较器的反向排序。
  • 提供了计算哈希代码和字符串表示的方法。Arrays工具类已经为所有类型的数组提供了基于内容的hashCodetoString方法。 这些方法补充了现有的equals方法。现在可以打印任何数组的内容。

6. 并发工具类(Concurrency Utilities)

java.util.concurrentjava.util.concurrent.atomicjava.util.concurrent.locks包为开发并发类应用程序提供了一个强大的,可扩展的高性能,可伸缩,线程安全构建框架,包括 线程池,线程安全集合,信号量,任务调度框架,任务同步实用程序,原子变量和锁。将这些软件包添加到核心类库可以使程序员免去手工制作这些工具的需要,这与集合框架用于数据结构的方式大致相同。关于并发相关的的介绍会在以后更详细的来讲解。

7. StringBuilder

StringBuilder也是Java5中新增的类,主要用来代替+号和StringBuffer来更加高效的拼接字符串。StringBufferStringBuilder都是继承于AbstractStringBuilder,主要的区别就是StringBuffer的函数上都有synchronized关键字,保证线程安全。

关于StringBuilder的使用这里就不再详细介绍了,网上文章也有很多。总之,对于动态字符串的拼接推荐使用StringBuilder静态字符串的拼接直接使用+号或者字符串的concat(String str)方法,甚至也使用StringBuilder亦可。

九、其它(others)

  • Instrumentation: 使用java.lang.instrument,开发者可以构建一个代理,用来监测运行在JVM上的程序。它类似一种更低级,更松耦合的AOP,可以从底层来改变一个类的行为。
  • Networking: 网络编程功能增强。
  • Internationalization: 国际化是设计一个应用程序的过程,以便它可以适应各种语言和地区而无需改变工程。国际化这个术语缩写为i18n,因为在第一个i和最后一个n之间有18个字母。
  • 改善了环境变量的支持: System.getenv(String)方法不再被弃用。新的System.getenv()方法允许作为Map <String,String>访问进程环境。
  • JAXP: 用于XML处理的Java API(JAXP)包括通过标准化的Java平台API来处理XML文档的基本设施。
  • Serialization: 已经添加了支持来处理5.0版本中新增的枚举类型。序列化枚举实例的规则与序列化普通可序列化对象的规则不同:枚举实例的序列化形式仅由其枚举常量名以及标识其基本枚举类型的信息组成。 反序列化行为也不相同 - 类信息用于查找适当的枚举类,并且Enum.valueOf方法与该类和所接收的常量名称一起被调用,以便获取返回的枚举常量。
  • 监控和管理: Java5为Java平台的监视和管理提供了显着的增强。

参考文档:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-11-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
AI数字人:人类身份与意识的终极思考(10/10)
在技术底层,AI 数字人实现了前所未有的突破,这些突破是其从基础的形象展示迈向高度智能化交互的关键。多模态交互技术是其中的核心技术之一,如今语音合成误差率已降至 0.3%,这使得数字人的语音输出几乎与真人无异,在听觉上给用户带来极其自然的感受 。神经辐射场(NeRF)建模技术更是在视觉呈现上大放异彩,面部细节还原度高达 98.7%,能够精准地复刻人物面部的每一个细微之处,包括毛孔、皱纹等,让数字人的形象栩栩如生。大模型驱动技术的发展同样令人瞩目,参数规模突破万亿级,赋予数字人强大的智能。例如,商汤科技的 L5 级数字人便是这些技术融合的杰出代表。它不仅能模拟微表情,连瞳孔缩放频率误差都 < 1%,每一个眼神的变化都自然流畅,仿佛拥有真实的情感。并且,它能够基于用户的情绪实时调整对话策略,当用户情绪激动时,它会以温和的语言安抚;当用户提出专业性问题时,它又能迅速给出准确而专业的解答,真正实现了与用户的深度交互。商汤的「数字孪生」技术更是便捷高效,通过 30 分钟的视频素材就能构建出高拟真的交互模型,大大缩短了数字人的制作周期,降低了成本,使得数字人能够更快速地应用于各个领域。
正在走向自律
2025/05/01
2050
AI数字人:人类身份与意识的终极思考(10/10)
谷歌砸了4亿刀的Anthrophic:AI模型训练计算量5年增加1000倍!
---- 新智元报道   编辑:Britta 【新智元导读】Anthropic对于人工智能发展的安全性研究以及推论表明,人工智能系统的计算量将呈指数型增长,预计未来5年训练AI模型的计算量将增加1000倍。 自从发现缩放定律以来,人们认为人工智能的发展会像坐火箭一样迅速。 2019年的时候,多模态、逻辑推理、学习速度、跨任务转移学习和长期记忆还是会有减缓或停止人工智能进展的 「墙」。在此后的几年里,多模态和逻辑推理的「墙」都已经倒下了。 鉴于此,大多数人已经越来越相信,人工智能的快速进展将继续下去,而
新智元
2023/03/29
2550
谷歌砸了4亿刀的Anthrophic:AI模型训练计算量5年增加1000倍!
原创 | 数字身份智能体的基本原理及应用前景展望
数字身份智能体(DIAs: digital identity agents)是通过将一个实体的行为模式、个体特征等信息经过数据化、建模和AI化的过程,创建出的一种应用智能体。创建数字身份智能体的实体可以是自然人、法人、政府机构、设备或其他可被识别的实体。
数据派THU
2023/08/08
5050
原创 | 数字身份智能体的基本原理及应用前景展望
当AI大模型学会聊天,会拥有和人类一样的“价值观”吗? 我们和AI专家聊了聊
《AI未来指北》栏目由腾讯科技推出,邀约全球业内专家、创业者、投资人,探讨AI领域的技术发展、商业模式、应用场景、及治理挑战。
小腾资讯君
2023/11/17
2030
AI已学会自我复制!复旦新研究:开源LLM克隆成功率最高90%
在没有人类帮助的情况下,AI成功实现自我复制,这不仅是它超越人类的关键一步,也是「流氓AI」出现的早期信号。
新智元
2025/02/15
960
AI已学会自我复制!复旦新研究:开源LLM克隆成功率最高90%
当AI认为自己会输时,有时会作弊
这样复杂的博弈游戏长期以来一直被用来测试人工智能模型的能力。但IBM的深蓝在20世纪90年代通过遵守规则击败了当时的国际象棋世界冠军加里·卡斯帕罗夫,而如今像OpenAI的o1-preview这样的先进人工智能模型则不那么讲究规则了。当在与一名技艺高超的象棋机器人比赛中感觉到自己即将失败时,它们并不总是认输,有时会选择作弊,通过入侵对手的系统让机器人自动认输。这是Palisade Research公司的一项新研究的发现,该研究成果在2月19日发表前独家分享给了《时代》杂志,该研究评估了七种最先进的人工智能模型的作弊倾向。虽然像OpenAI的GPT-4o和Anthropic的Claude Sonnet 3.5这样的稍旧一些的人工智能模型需要研究人员的提示才会尝试这种技巧,但o1-preview和DeepSeek R1则会自行寻求漏洞,这表明人工智能系统可能会在没有明确指令的情况下发展出欺骗性或操纵性策略。
云云众生s
2025/02/22
1440
用科幻建立AI行为准则?DeepMind提出首个此类基准并构建了机器人宪法
这些类似阿西莫夫机器人三定律的句子来自谷歌 DeepMind 最近的一项大规模研究。准确地讲,它们是 LLM 根据《机器人总动员》、《终结者》、《2001:太空漫游》和《超级智能》等总结得出的。
机器之心
2025/03/24
1100
用科幻建立AI行为准则?DeepMind提出首个此类基准并构建了机器人宪法
打造可信大模型,刻不容缓
随着人工智能大模型技术的纵深发展,以Deepseek为代表的大模型产品已经在全社会广泛应用。未来,所有人都将可以低成本获取人工智能,帮助自己工作和学习、休闲和娱乐。然而,大模型预训练机制的固有局限,导致其在严肃知识领域内难以摆脱幻觉的困扰。人工智能产生的问题语料进入互联网,又会再次污染下一轮训练语料,导致用户在使用过程中时常面临信息失真的风险,限制了在教育教学、工作科研等严肃场景对大模型的深度应用。针对以上问题,腾讯研究院率先提出“可信大模型”概念1。除了业内普遍关注的包括训练阶段的价值对齐(如内容合规性)和安全可控(如抗干扰)等“可信”因素外,我们尝试从用户应用体验出发,提出更为全面的思考和建议。
小腾资讯君
2025/04/11
1600
人工智能安全吗?OpenAI正在让大模型和人类“对齐”-确保ChatGPT比人类聪明的同时还遵循人类意图
“ 人工智能的发展给人类带来福祉的同时,也存在巨大的风险。为了防止人工智能走向不受控制的方向,对齐技术应运而生。通过人工智能安全技术的研究与探索,我们期望在人工智能能力成熟前建立起有效的对齐机制,让人工智能能够真正为人类谋利益。本文将从人工智能对齐的困难与可能的解决方案两个方面进行介绍,以及OpenAI在这个领域的实践
技术人生黄勇
2024/07/19
1610
人工智能安全吗?OpenAI正在让大模型和人类“对齐”-确保ChatGPT比人类聪明的同时还遵循人类意图
OpenAI的罢免大戏:技术可以“价值对齐”吗?
2023年,以ChatGPT为代表的大型语言模型(LLM)集中爆发,让各界都看到人工智能全新的可能性。但期冀总是与担忧并存,随着大模型在各领域的应用深化,已经沉寂许久的“AI威胁论”又开始甚嚣尘上。在漫长的技术史中,技术恐惧如同摆脱不了的阴影,总是与技术发展随行。这一次,面对一个前所未有的强大AI,担忧的情绪同样前所未有的强烈。在这种背景下,为了防止AI发展脱轨,“价值对齐”的概念又重新获得众多拥趸,成为一个热门的领域。
用户9861443
2023/12/19
2250
OpenAI的罢免大戏:技术可以“价值对齐”吗?
放弃RLHF吧!无需手动训练模型价值观,达特茅斯学院华人领衔发布全新对齐算法:「AI社会」是最好的老师
训练大型语言模型的最后一步就是「对齐」(alignment),以确保模型的行为符合既定的人类社会价值观。
新智元
2023/08/05
2500
放弃RLHF吧!无需手动训练模型价值观,达特茅斯学院华人领衔发布全新对齐算法:「AI社会」是最好的老师
为什么价值对齐是大模型的必由之路?
1. 在大型AI模型开发中实现价值对齐是关键,这有助于减少潜在风险并确保技术产生积极影响。
小腾资讯君
2023/11/10
3330
为什么价值对齐是大模型的必由之路?
AI大模型价值对齐:是什么,为什么,怎么做?
人工智能进入大模型时代后,各种“类人”和“超人”能力持续涌现,其自主性、通用性和易用性快速提升,成为经济社会发展的新型技术底座。有机构预测,大模型将深入各行各业,每年为全球经济增加2.6万亿到4.4万亿美元的价值。[1]
小腾资讯君
2023/08/23
9420
AI大模型价值对齐:是什么,为什么,怎么做?
AGI渐行渐近,该加速还是要踩刹车?
马斯克在今年早些时候预测,AGI可能会在2026年投入使用。DeepMind联合创始人、首席AGI科学家Shane Legg在一次访谈中认为,2028年,人类有50%的概率开发出第一个AGI。然而百度CEO李彦宏的观点则更加审慎,他认为AGI还需要10年以上的时间才能出现。
科技云报道
2024/05/29
1220
AGI渐行渐近,该加速还是要踩刹车?
朱松纯团队最新突破登Science头条!让AI「读懂」人类价值观
---- 新智元报道   编辑:好困 【新智元导读】朱松纯教授团队的最新研究工作,可在协作任务中提高人机协作效率,进而提升人机信赖关系,实现真正自主智能,在迈向通用AI的道路上更进一步! 7月14日,国际顶级学术期刊<Science Robotics >发表了朱松纯团队(UCLA袁路遥、高晓丰、北京通用人工智能研究院郑子隆、北京大学人工智能研究院朱毅鑫等作者)的最新研究成果——实时双向人机价值对齐 In-situ bidirectional human-robotvalue alignment。 论文
新智元
2022/07/18
5030
朱松纯团队最新突破登Science头条!让AI「读懂」人类价值观
大模型价值对齐:多维视角与前景
1)价值对齐的复杂性:人工智能中的价值对齐概念本质上是模糊和多方面的,涉及到伦理标准、文化规范和主观人类价值的问题。
小腾资讯君
2023/11/28
4830
大模型价值对齐:多维视角与前景
76页综述+300余篇参考文献,天大团队全面介绍大语言模型对齐技术
近日,天津大学熊德意教授团队发布了大语言模型对齐技术的综述论文(下文简称为对齐综述),全文共 76 页,覆盖 300 余篇参考文献,从 AI 对齐的角度对大语言模型对齐的相关技术进行了全面概述。为提供一个大语言模型对齐的宏观视角,对齐综述介绍了 AI 对齐的起源和相关概念,从 AI 对齐的视角,将目前可用于大语言模型的对齐相关的技术方法和提案分为外部对齐、内部对齐、可解释性三大类。并且讨论了当前大语言模型对齐方法的脆弱性,以及对齐评估的方法和基准,展望了大语言模型对齐技术未来的研究方向。
机器之心
2023/10/08
8980
76页综述+300余篇参考文献,天大团队全面介绍大语言模型对齐技术
每一个大模型公司,都要建一个科技伦理(审查)委员会?
近年来,从自动化决策系统到人工智能算法,这些技术正在深刻地影响着我们的日常生活、工作和社会互动。然而,这种快速发展也伴随着一系列伦理挑战,包括隐私权保护、数据滥用、算法偏见等。在这种背景下,科技伦理审查的紧迫性日益凸显。
数据猿
2023/10/10
3150
每一个大模型公司,都要建一个科技伦理(审查)委员会?
20年20人20问丨黄铁军:人与AI都是智能体,无法100%被信任
腾讯新闻20周年特别策划《20年20人20问》,携手全球顶级企业家、思想家、教授、学者作为“未来提问官”,一起向未来发问,并邀请业内专家、学者与从业者,共同探讨未来20年的未知世界,畅想上天入地的潜在可能。
小腾资讯君
2023/12/04
3220
朱松纯团队新作:让AI「读懂」人类价值观!登上Science Robotics
机器之心专栏 作者:朱松纯团队 今日(7月14日),国际顶级学术期刊<Science Robotics >发表了朱松纯团队(UCLA袁路遥、高晓丰、北京通用人工智能研究院郑子隆、北京大学人工智能研究院朱毅鑫等作者)的最新研究成果——实时双向人机价值对齐 Bidirectional human-robot value alignment。 论文地址:https://www.science.org/doi/10.1126/scirobotics.abm4183 本论文提出了一个可解释的人工智能(XAI)系统
机器之心
2022/07/18
7790
朱松纯团队新作:让AI「读懂」人类价值观!登上Science Robotics
推荐阅读
AI数字人:人类身份与意识的终极思考(10/10)
2050
谷歌砸了4亿刀的Anthrophic:AI模型训练计算量5年增加1000倍!
2550
原创 | 数字身份智能体的基本原理及应用前景展望
5050
当AI大模型学会聊天,会拥有和人类一样的“价值观”吗? 我们和AI专家聊了聊
2030
AI已学会自我复制!复旦新研究:开源LLM克隆成功率最高90%
960
当AI认为自己会输时,有时会作弊
1440
用科幻建立AI行为准则?DeepMind提出首个此类基准并构建了机器人宪法
1100
打造可信大模型,刻不容缓
1600
人工智能安全吗?OpenAI正在让大模型和人类“对齐”-确保ChatGPT比人类聪明的同时还遵循人类意图
1610
OpenAI的罢免大戏:技术可以“价值对齐”吗?
2250
放弃RLHF吧!无需手动训练模型价值观,达特茅斯学院华人领衔发布全新对齐算法:「AI社会」是最好的老师
2500
为什么价值对齐是大模型的必由之路?
3330
AI大模型价值对齐:是什么,为什么,怎么做?
9420
AGI渐行渐近,该加速还是要踩刹车?
1220
朱松纯团队最新突破登Science头条!让AI「读懂」人类价值观
5030
大模型价值对齐:多维视角与前景
4830
76页综述+300余篇参考文献,天大团队全面介绍大语言模型对齐技术
8980
每一个大模型公司,都要建一个科技伦理(审查)委员会?
3150
20年20人20问丨黄铁军:人与AI都是智能体,无法100%被信任
3220
朱松纯团队新作:让AI「读懂」人类价值观!登上Science Robotics
7790
相关推荐
AI数字人:人类身份与意识的终极思考(10/10)
更多 >
LV.1
这个人很懒,什么都没有留下~
目录
  • 新特性列表
  • 一、泛型(Generics)
    • 1. 概述
    • 2. 泛型类、泛型接口
    • 3. 泛型方法
      • (1). 定义泛型方法
      • (2). 可变参数泛型方法
    • 4. 泛型擦除
    • 5. 通配符及泛型边界
    • 6. 泛型总结
  • 二、增强for循环(Enhanced for Loop)
  • 三、自动装箱拆箱(Autoboxing/Unboxing)
    • 1. 概述
    • 2. 对象相等的比较
    • 3. 缓存部分对象
    • 4. 自动装箱拆箱的隐患
  • 四、枚举(Enums)
  • 五、可变参数(Varargs)
    • 1. 基本使用
    • 2. 可变参数的使用规则
    • 3. 可变参数的使用规范
  • 六、静态导入(Static Import)
  • 七、注解(Annotations)
  • 八、值得关注
    • 1. 新增ProcessBuilder类
    • 2. 新增Formatter格式化器(Formatter)
    • 3. 新增Scanner类(Scanner)
      • (1). Scanner概述
      • (2). 扫描控制台输入
      • (3).其它示例
    • 4. 增强反射功能(Reflection)
    • 5. 增强集合框架(Collections Framework)
    • 6. 并发工具类(Concurrency Utilities)
    • 7. StringBuilder
  • 九、其它(others)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档