文档:lambda表达式&内部类.note
链接:http://note.youdao.com/noteshare?id=686820bc4907b59c95cb08114caf1e7a&sub=D71C03E7B6D845DDB1C6CFE69EB1E4E8
一、代码块
1.1、静态代码块
说明
使用static修饰的一段用{}包裹起来Java代码段
与成员变量同级
在类加载时执行
static{
Java代码块
}
1.2、成员代码块
说明
在类的成员中添加代码块,不能使用权限修饰符
在构造方法执行前执行
执行结束后销毁
修饰符 class 类名{
//其他类成员
//成员代码
{
//Java代码
}
}
1.4、本地代码块
说明
将代码块定义在方法中
在括号所在的区域产生一个作用域
方法(){
//代码
//成员代码
{
//Java代码
}
//代码
}
二、内部类
2.1、静态内部类
说明
一个定义在其他类型内部的类型称为内部类
使用static修饰符修饰内部类
静态内部类可以使用所有的权限修饰符
当外部有权限使用时,外部类对于使用者充当包的作用
当在内部类创建类型时,外部类可以省略
权限修饰符 class 外部类{
.....
权限修饰符 static class 内部类{
....
}
}
内部类 对象名= new 外部类.内部类构造方法();
示例
public class DemoStaticInnerClass {
/**
* 静态内部类
*/
public static class Student{
private long id;
private String name;
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
public Student(Long id, String name) {
this.id = id;
this.name = name;
}
public static void main(String[] args) {
Student student = new Student(1L,"大黄");
System.out.println(student);
}
}
/**
* @param args
*/
public static void main(String[] args) {
//使用静态内部类 内部类 对象名= new 外部类.内部类构造方法();
DemoStaticInnerClass.Student stu=new DemoStaticInnerClass.Student((long) 1, "李三");
System.out.println(stu);
}
2.2、成员内部类
说明
不使用static修饰的内部类。
只有在对象创建之后,类型才会存在
成员内部类可以使用所有的权限修饰符
成员内部类可以直接调用外部类的其他成员
成员内部类对象必须在外部类对象创建后创建
成员内部类在外部对象创建时创建,对象销毁后销毁
成员内部类中this关键字主要表达成员内部类,可以通过
外部类.this的方式表示外部类对象引用
权限修饰符 class 外部类{
....
权限修饰符 class 内部类{
.....
}
.....
}
内部类 对象名= 外部类对象.new 内部类构造方法();
内部类 对象名= new 外部类构造方法.new.内部类构造方法();
示例
public class DemoInnerClass {
private String name="yang";
/**
* 私有成员内部类
* @author dawulei
*
*/
private class Student{
private String name="海洋";
public void print(){
String line="外部姓名"+DemoInnerClass.this.name+
"内部姓名"+this.name;
}
}
public Student buildStudent() {
return this.new Student();
}
/**
* 共有成员内部类
*/
public class Teacher{
private long id;
private String name;
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
public class UseInnerClass {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println(new DemoInnerClass().buildStudent());
//获得外部类对象才能构造内部类对象
Teacher theacher = new DemoInnerClass().new Teacher();
//输出
System.out.println(theacher);
}
}
2.3、本地类
说明
将类型定义在方法中
类型的声明周期从类的定义时期,一直到类型所在的大括号结束位置,与变量声明周期一直
权限修饰符 class 外部类{
方法(){
class 类名{
.....
}
}
}
2.4、匿名内部类
说明
没有名称的类型定义
匿名内部类所在需要创建接口实现类对象或者子类对象,但不希望书写类型实现接口或实现父类对象时
使用
匿名内部类在方法中定义时可以直接使用类型外部的局部变量(JDK1.8之前需要使用final修饰),但方法的局部变量对于匿名内部类而言是只读的。
匿名内部类在编译成class文件时,文件名为外部类名后拼接美元符号再拼接出现匿名内部类的顺序。
父类或接口 引用名=new 父类或接口名(){
//匿名内部类成员
}
示例
随机生成两个汉字
public class DemoAnonymoseClass {
/**
* @param args
*/
public static void main(String[] args) {
Runnable task = new Runnable() {
private Random rand = new Random();
private String buildName() {
StringBuilder nameBuilder = new StringBuilder();
// 4E00 - 9FA5
nameBuilder.append((char)(rand.nextInt(0x9fa5-0x4e00)+0x4e00));
nameBuilder.append((char)(rand.nextInt(0x9fa5-0x4e00)+0x4e00));
return nameBuilder.toString();
}
private String name;
@Override
public void run() {
while(true) {
name = buildName();
System.out.println(name);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
new Thread(task).start();
// 重写父类Object的toString方法
Object obj = new Object() {
@Override
public String toString() {
return "自定义方法的对象输出";
}
};
System.out.println(obj);
}
}
三、Lambda表达式
3.1、说明
Lambda表达式目标使用最小可能的语法定义函数
Lambda表达式本质上上就是Java中的函数式编程
Lambda表达式产生的是函数而不是类型,在Java的虚拟机中所有东西都是类型,因此虚拟机在后台做了很多操作让Lambda表达式看起来更像函数
Lambda表达式在语法上更可能的灵活,以便于开发和使用
如果可以推到出lambda表达式的参数类型,则可以忽略其类型。
如果方法只有一个参数,而且这个参数可以推到得出,可以省略这个括号
lambda表达式的返回类型总是会由上下文推到得出
功能接口是仅包含一个抽象方法的任何接口 。(一个功能接口可能包含一个或多个 默认方法或 静态方法。)由于一个功能接口仅包含一个抽象方法,因此在实现该方法时可以省略该方法的名称。为此,您可以使用lambda表达式(而不是使用匿名类表达式)
3.2、语法
参数、箭头(->)、表达式
(String first,String second)->
first.length()-cecond.langth()
//检查一个字符串比另一个字符串短
方法
把代码放在{}中,并包含显示的return
(String first,String second)->{
if(first.length()<cecond.langth())return -1;
else if(first.length()>cecond.langth())return 1;
else return 0;
}
如果没有参数,仍要提供括号
()->{for(i=0;i<100;i++)System.out.println(i);}
四、方法引用
说明
当Lambda表达式只是需要调用一个已经存在的方法即可实现时,此时使用方法的引用替代Lambda表达式。
方法主要关注方法,要求接口的实现方法与被引用的方法在返回值类型、参数列表上完全相同
被引用的可以是对象上的方法,也可以是类型上的方法
可以人为方法引用是Lambda表达式的一种升级版本。
静态方法引用
接口 引用名称= 类型或接口名称::方法名;
对象方法引用
接口 引用名称= 对象::方法名;
本地类:如果您需要创建一个类的多个实例,访问其构造函数或引入新的命名类型(例如,因为稍后需要调用其他方法),请使用它。
匿名类:如果需要声明字段或其他方法,请使用它。
Lambda表达式:
如果要封装要传递给其他代码的单个行为单位,请使用它。例如,如果要在集合的每个元素上执行特定操作,流程完成或流程遇到错误时,可以使用lambda表达式。
如果您需要功能接口的简单实例并且不符合上述条件(例如,不需要构造函数,命名类型,字段或其他方法),请使用它。
嵌套类:如果您的要求与本地类的要求相似,并且您想使该类型更广泛地使用,并且您不需要访问本地变量或方法参数,请使用它。
如果您需要访问封闭实例的非公共字段和方法,请使用非静态嵌套类(或内部类)。如果您不需要此访问,请使用静态嵌套类。