Lambda表达式是java8的重要更新,也是被广大程序员期待已久的新特性。
/*
* 1.Lambda表达式支持将代码块作为方法的参数;允许使用更加简洁的代码创建只有一个抽象方法的接口(函数式接口)的对象,
* 返回值是明确类型的接口对象,
* 2.Lambda表达式的主要作用是替代匿名内部类的繁琐语句,由三部分组成
* 1>形参列表,允许省略形参的类型,如果只有一个形参,则可以省略圆括号
* 2>箭头 ->
* 3>代码块:若代码块只有一条语句,它允许省略花括号,其只有一个返回值,若只有一条语句,则可以省略return,自动返回该语句的值
* 3.Lambda表达式实际上会被当成任意类型的对象,至于被当成何种对象,这取决于运行环境的需要
* 4.Lambda表达式与函数式接口:
* 1>函数式接口,只允许包含一个抽象方法的接口,但是可以包含多个默认方法和类方法
* 2>@FunctionalInterface注解,注解函数式接口
* 3>返回值是明确类型的函数式接口,可以用他声明变量,强制类型转换,作为方法的实参
* 4>如果两个接口拥有相同的抽象方法,则其对应的Lambda表达式将可以返回这两种类型
*/
//使用Lambda表达式代替匿名内部类
public class LambdaTest
{
public static void main(String[] args)
{
//之前定义好的用于处理数组的类
ProcessArray pr = new ProcessArray();
int[] array = {2,3,-2,-5};
pa.process(array, (int[] array)->
{
int sum = 0;
for(int tem : array)
sum += tem;
return sum
});
}
}
//使用Lambda表达式创建函数式接口的对象
Runnable r = ()->{
for(int i=0 ; i<100 ;i++)
System.out.println(i);
};
/*
* 5.方法引用和构造器引用:前提,Lambda表达式的代码块只有一个语句
*/
Convertion c = str -> Integer.parseInt(str) ;
等价于
Convertion c = Integer::parseInt; //没有小括号
/*
* 6.Lambda表达式与匿名内部类
* 相同:Lambda表达式与匿名内部类一样,可以访问effectively final的局部变量与外部类的成员变量(实例变量,类变量)
* 生成的对象都可以直接调用从接口继承的方法
* 区别:匿名内部类可以为任意接口创建对象,无论这个对象包含多少抽象方法,只要都实现了即可;而Lambda表达式只能为包含一个抽象方法的接口创建实例
* 匿名内部类可以为抽象甚至普通类创建实例,而Lambda表达式不可以
* 匿名内部类实现的抽象方法的方法体允许调用接口中定义的默认方法,而Lambda表达式不可以
*/
枚举类:
在某些情况下,一个类的实例是有限而且固定的,比如季节类,他只有四个对象。这些实例有限且固定的类,在java中被称为枚举类。
package enumclass;
/*
* 1.enum关键字用来定义枚举类,枚举类是一种特殊的类,可以有自己的变量,方法,构造器,一个java源文件中只有一个public枚举类
* 2.枚举类与普通类的区别
* 2.1 枚举类可以实现一个或多个接口,但是枚举类的父类是java.lang.Enum,而不是java.lang.Object,所以枚举类不能显示的继承其他父类
* 2.2 使用enum定义的非抽象类,默认使用final修饰,不能派生子类,而抽象类(无需使用abstract修饰)可以派生子类
* 2.3 枚举类的构造器只能是private
* 2.4 枚举类的所有实例必须在第一行显示列出,默认public static final修饰,否则不能产生子类
* 3.一般讲枚举类设计成不可变类,其中的成员变量都使用private final修饰,则创建实例时用构造器显示的赋值
* 4.实现接口的枚举类,可实现一个或多个方法,可分别对枚举值设置不同的方法实现
* 4.1 为不同的枚举值设置不同的方法实现,大括号内实际是类体的部分,相当于创建SeasonEnum匿名子类的实例,而不是直接
* 创建SeasonEnum的实例,编译之后会看到5个.class文件,其中带标号的4个是匿名子类的实例
* 5.包含抽象方法的枚举类,类似继承接口,只不过抽象方法是枚举类自己定义的
* 5.1 当枚举类中定义了抽象方法时,不需要将该枚举类用abstract修饰,系统自动添加
* 5.2 枚举类需要显示的创建实例,而不是作为父类,所以定义枚举值时要为每个抽象方法提供方法实现
*/
interface SeasonDesc
{
void info();
}
enum SeasonEnum implements SeasonDesc //一般将枚举类设计成不可比纳雷
{
//SPRING,SUMMER,FALL,WINTER; 枚举实例
SPRING("春天")
{
public void info()
{
System.out.println("春天真好");
}
}
,SUMMER("夏天")
{
public void info()
{
System.out.println("夏天真好");
}
}
,FALL("秋天")
{
public void info()
{
System.out.println("秋天真好");
}
},
WINTER("冬天")
{
public void info()
{
System.out.println("冬天真好");
}
}; //枚举实例,调用带参构造器
private String name;
private SeasonEnum(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
/* 所有枚举值调用该方法的实现都是相同的
public void info()
{
System.out.println("一年四季");
}*/
}
/* SeasonEnum主要用于创建实例,无法被继承
enum ll extends SeasonEnum
{
}*/
public class EnumTest
{
public void judge(SeasonEnum s)
{
switch(s) //switch中可以是枚举值
{
case SPRING: //无需添加枚举类做限定
System.out.println("春暖花开");
break;
case SUMMER:
System.out.println("烈日炎炎");
break;
case FALL:
System.out.println("秋高气爽");
break;
case WINTER:
System.out.println("银装素裹");
break;
}
}
public static void main(String[] args)
{
for (SeasonEnum s : SeasonEnum.values()) //遍历所有枚举值
{
System.out.println(s); //打印出所有枚举值名
}
new EnumTest().judge(SeasonEnum.SPRING);
SeasonEnum s = SeasonEnum.valueOf(SeasonEnum.class, "SPRING"); //获取对应枚举值
s.info();
SeasonEnum s1 = SeasonEnum.valueOf("FALL");
System.out.println(s1.getName()); //秋天
s1.info();
}
}
垃圾回收机制:
垃圾回收是java语言的重要功能之一
/*
* 1.当程序创建对象,数组类型的引用类型实体时,系统都会在堆内存中为之分配内存,当这块内存不再被任何变量所引用时,就变成了垃圾
* 1.1 java中的垃圾回收机制负责回收堆内存中的对象,但是不负责回收任何物理资源(数据库连接,IO等)
* 1.2 系统无法精确的控制垃圾回收机制的运行,当对象永久性的失去引用时,他会在合适的时候对其占用的内存进行回收
* 1.3 在垃圾回收之前,可能会调用对象的finalize()方法,该方法可能使得该对象重新获得引用,从而导致无法回收
* 2.对象在内存中的状态:
* 2.1 一个对象被方法的局部变量引用时,当方法执行完毕该对象进入可恢复状态
* 2.2 当一个对象被一个类的类变量引用时,当类被销毁,该对象才会变为可恢复状态
* 2.3 当一个对象被类的实例变量锁引用时,当对象被销毁,该对象才变为可恢复状态
* 3.强制垃圾回收
* System.gc() ; Runtime.getRuntime.gc();
* 4.finalize()方法,在垃圾回收器回收某个对象之前,通常要求调用适当的方法清理资源,默认的方法就是finalize()
* 4.1 不要主动调用对象的finalize方法,应将其交给垃圾回收机制
* 4.2 finalize方法何时被调用,是否被调用具有不确定性,不要把它当做一定会执行的方法,所以不建议在该方法中回收对象占用的资源
* 4.3 当JVM执行某个对象的finalize方法时,可以使该对象或其他对象重新变为可达状态
* 4.4 当JVM执行该方法遇到异常时,不会报告异常,而是继续执行
*/
// 通知垃圾回收器进行垃圾回收
public class Gctest
{
public static void main(String[] args)
{
for(int i=0; i<3 ; i++)
{
new Gctest();
//System.gc(); 建议垃圾回收器进行垃圾回收,同下
Runtime.getRuntime().gc();
}
}
public void finalize()
{
System.out.println("系统正在回收Gctest对象");
}
}
对象在内存中的状态,补充:也有可能某个对象创建完成之后就变成可恢复状态,但这种不常用
//在finalize方法中使对象重新获得引用
public class Gctest
{
public static Gctest gct = null;
public void test()
{
System.out.println("测试清理资源的finalize方法");
}
public static void main(String[] args)
{
new Gctest(); //该对象创建时就变为可恢复状态
System.gc(); //通知来回收器进行垃圾回收
Runtime.getRuntime().runFinalization(); //调用对象的finalize方法,不然不一定会调用,则将出现空指针异常
//System.runFinalization(); //效果同上
gct.test(); //测试清理资源的finalize方法,将要被处理的对象在finalize中重新获得引用变为可达状态
}
public void finalize()
{
gct = this; //this表示将要被处理的对象
}
}
/*
* 5 对象的强,软,弱,虚引用
* 5.1 对象的强引用时我们最常使用的引用方法,即将引用变量指向创建的对象或数组
* 5.2 软引用需要通过SoftReference类来实现,当一个对象只有软引用时,可以被垃圾回收,当内存紧张时会自动进行可垃圾回收
* 5.3 弱引用WeakReference类来实现,与软引用相似,只是即使内存不紧张,它也可能被垃圾回收
* 5.4 虚引用:PhantomReference类实现,相当于没有引用,与ReferenceQueue类一起使用,当对象被垃圾回收时,该引用会被放到引用队列中,
* 以此来监视对象的回收状态
* 5.5 如果对象想要被垃圾回收,则必须切断所有的强引用
* 5.6 常量池中的对象不会被垃圾回收
*/
//弱引用测试
public class Gctest
{
public static void main(String[] args)
{
String str = new String("大好人"); //此处用String str = "大好人"将得不到预期效果
WeakReference wr = new WeakReference(str);
str = null;
System.out.println(wr.get()); //获得引用所指向的对象 大好人
System.gc();
System.out.println(wr.get()); //null ,对象已经被回收
}
}
//虚引用测试
public class Gctest
{
public static void main(String[] args)
{
String str = new String("大好人");
ReferenceQueue fq = new ReferenceQueue();
PhantomReference pr = new PhantomReference(str, fq);
str = null;
System.out.println(pr.get()); //虚引用无法获取引用对象
System.gc();
System.runFinalization(); //调用finalize方法之后才将虚引用加入到引用队列中
System.out.println(fq.poll() == pr); //true
}
}
java中修饰符的使用范围汇总: