JDK8中有双冒号的用法,形如Class::methodname,符号左边是调用方法所处的类名,符号右边是调用的静态方法。简单的说,就是逐一传入参数值到某个类的静态方法并调用该静态方法。
以前的方式
public static void printValue(String str){
System.out.println("print value : "+str);
}
public static void main(String[] args) {
List list = Arrays.asList("a","b","c","d");
for (String a: list) {
Test.printValue(a);
}
System.out.println("===============================");
//下面的for each循环和上面的循环是等价的
list.forEach(s->{
Test.printValue(s);
});
}
print value : a
print value : b
print value : c
print value : d
===============================
print value : a
print value : b
print value : c
print value : d
现在使用双冒号的方式
public static void print(String str) {
System.out.println("print vlistue : " + str);
}
public static void main(String[] args) {
List list = Arrays.asList("a", "b", "c", "d");
list.forEach(Test::print);//遍历集合的元素,并逐一传入调用的静态方法中,实现各元素的打印
System.out.println("=======================================");
//下面的方法和上面的方法是等价的
Consumer methodParam = Test::print; //定位到调用方法的参数位置
list.forEach(s -> methodParam.accept(s));//遍历传送元素-定位处逐一接收传送过来的各元素,并打印
}
print vlistue : a
print vlistue : b
print vlistue : c
print vlistue : d
=======================================
print vlistue : a
print vlistue : b
print vlistue : c
print vlistue : d
有的时候,我们还会看到Object::的用法
其实用法也差不多,只不过Class::function的形式中function是属于Class的,可以是静态方法也可以是非静态方法。而Object::的形式中funtion是属于这个对象的,可以是静态方法也可以是非静态方法。Object::中比较特殊的代表就是this::的用法了,指向当前对象。
下面,来看看几种用法示例。
1)System.out::println
public static void main(String[] args) {
String[] array = {"aa", "xx", "ss"};
List list = Arrays.asList(array);
//Java 7
for(String s:list){
System.out.println(s);
}
//Java 8
list.forEach(System.out::println);
}
说明:System.out是一个对象,而且是一个PrintStream类型的实例。println是PrintStream类中的一个非静态方法。
System.out.println()的真正含义
out是System类中的一个静态属性,默认值为null,类型为PrintStream。System.out的实例化是通过System类中的initializeSystemClass方法完成的,在虚拟机加载的时候完成初始化。
2)instance::print
public class Test {
public static void main(String[] args) {
List list = Arrays.asList("aa", "xx", "ss");
//形如 instanceRef::methodName
list.forEach(new Demo()::print);
}
}
class Demo{
public void print(String content){
System.out.println(content);//aa xx ss
}
}
3)super::print
public class Test extends Demo{
public void invokePrint(){
List list = Arrays.asList("aa", "xx", "ss");
//形如 instanceRef::methodName
list.forEach(super::print);
}
public static void main(String[] args) {
new Test().invokePrint();
}
}
class Demo{
public void print(String content){
System.out.println(content);//aa xx ss
}
}
4)this::print
public class Test extends Demo{
public void invokePrint(){
List list = Arrays.asList("aa", "xx", "ss");
//形如 instanceRef::methodName
// list.forEach(super::print);
list.forEach(this::print);
}
@Override
public void print(String content){
System.out.println("【子类-重写】"+content);
}
public static void main(String[] args) {
new Test().invokePrint();
}
}
class Demo{
public void print(String content){
System.out.println(content);
}
}
5)类无参构造器语法-Class::new
public class Test {
public void test() {
InterfaceTest com = Test::new;//这里并不是真正的实现,而是绑定new Test操作(关联)到接口方法
Test bean = com.create();//调用create方法时才真正触发new Test()操作
System.out.println(bean);
}
public static void main(String[] args) {
new Test().test();
}
}
interface InterfaceTest{
Test create();
}
说明:通过idea的标记提示好像Test实现了InterfaceTest,但其实并没有真正实现InterfaceTest!
6)类有参构造器语法-Class::new
public class Test {
private String name;
Test(String name){
this.name = name;
}
Test(){
}
public void test() {
InterfaceTest com = Test::new;//这里并不是真正的实现,而是绑定new Test操作(关联)到接口方法
Test bean = com.create("hello world");//调用create方法时才真正触发new Test("hello world")操作
System.out.println(bean);
System.out.println(bean.name);
}
public static void main(String[] args) {
new Test().test();
}
}
interface InterfaceTest{
Test create(String name);
}
Test@161cd475
hello world
7)数组构造器语法-Test[]::new
借用jdk自带的java.util.function.Function接口实现
public class Test {
public static void main(String[] args) {
Function function = Test[]::new;//关联操作到接口方法
Test[] array = function.apply(3);//真正调用,创建大小为3的数组
for (Test e : array) {
System.out.println(e);//输出3个空对象(null)
}
}
}
使用自定义接口实现(需要使用@FunctionalInterface注解标记)
public class Test {
public static void main(String[] args) {
Interface function = Test[]::new;
Test[] array = function.apply(3);
for(Test e:array){
System.out.println(e);
}
}
}
@FunctionalInterface
interface Interface{
T apply(A a);
}
8)ArrayList::new
可以这么操作
public static void main(String[] args) {
List list = new ArrayList<>();
list.add("alpha");
list.add("beta");
list = list.stream().map(s -> s.toUpperCase()).collect(Collectors.toList());
System.out.println(list);//[ALPHA, BETA]
}
也可以这么操作
public static void main(String[] args) {
List list = new ArrayList<>();
list.add("alpha");
list.add("beta");
//String::toUpperCase表示String的非静态方法被各个元素调用
list = list.stream().map(String::toUpperCase).collect(Collectors.toCollection(ArrayList::new));
System.out.println(list);//[ALPHA, BETA]
}
还可以这么操作
public static void main(String[] args) {
List list = new ArrayList<>();
list.add("alpha");
list.add("beta");
//调用Strings的toUpperCase静态方法
list = list.stream().map(Strings::toUpperCase).collect(Collectors.toCollection(ArrayList::new));
System.out.println(list);//[ALPHA, BETA]
}