Java日志五「内部类和Lambda表达式」

**

内部类

**
内部类就是定义在一个类里面的类。有三种:
1.成员内部类
2.局部内部类
3.匿名内部类

我们先来看第一种成员内部类:
定义一个外部类(Body)和一个成员内部类(Heart),格式如下:

public class Body {

	public class Heart
	{
		String name="heart";
		
		public void methodHeart() 
		{
		System.out.println("heart类方法");
		System.out.println("我是"+name);
		System.out.println("我叫"+Body.this.name);//与使用super不同,需要这样来访问外部类成员变量
		}
		
		
	}
	
	private String name="gfx";
	
	public void methodBody() 
	{
		System.out.println("body类方法");
		new Heart().methodHeart();
	}
}

有五点注意事项:
1.作为外部类权限修饰符只有public和(default)
2.成员内部类,权限修饰符四种都可以
3.内部类可以随意访问外部类的成员变量和成员方法
4.内部类想使用外部类的成员变量要使用——外部类类名.this.成员变量名的格式。
5.外部类想要使用内部类的成员方法要使用对象调用(间接使用),外部类methodBody方法调用内部类methodHeart方法。

我们看一下main方法的运行结果

public static void main(String[] args) {
	Body body=new Body();
		
	Body.Heart heart=new Body().new Heart();//创建一个内部类对象
		
	body.methodBody();
	
	System.out.println("==================");
		
	heart.methodHeart();
}

结果

Body类方法
heart类方法
我是heart
我叫gfx
==================
heart类方法
我是heart
我叫gfx

第二种局部内部类:
局部内部类是定义在一个方法之内的类,不可以被外面的方法访问到,并且定义的时候不可以写权限修饰符。下面在Body类中定义一个methodBody2方法,在其中定义一个局部内部类(Brain):

public void methodBody2() 
	{
		int num=10; 
		class Brain//局部内部类,不能写权限修饰符
		{
			public void methodBrain()
			{
				System.out.println("Brain(局部内部类)类方法");
			}
			
			public void getNum() 
			{
				System.out.println(num);
			}
		}
		Brain brain=new Brain();//因为在方法外面就不可以使用Brain类了,所以要在方法内部进行定义
		brain.methodBrain();
	}

一个局部内部类的使用,一个非常重要的注意事项是,局部内部类访问所在方法的局部变量的时候,该变量一定要是有效final的

所谓的有效final的局部变量就是该局部变量不可以被改变,methodBody2方法中的局部变量num,并没有加final关键字来修饰,但是num没有被改变,所以num也是有效final的局部变量。

要这样做的原因是局部变量在方法结束就从内存消失了,但局部内部类不一定会消失,所以在使用局部变量的时候就复制该值,所以要求保持不变。

在main中运行

public static void main(String[] args) {
	body.methodBody2();
}

结果

Brain(局部内部类)类方法

第三种匿名内部类,使用匿名内部类时,一般都是接口的实现类或者父类的子类只需要用唯一的一次,那么使用匿名内部类可以大大节省时间。

我们来定义一个简单的接口

public interface MyInterface {
	public void method();

}

现在我们想使用这个接口,之前都是先创建一个实现类,然后重写抽象方法,然后在main中创建对象等等步骤,非常麻烦,现在我们使用匿名内部类可以大大减少代码量。

在mian方法中使用

public static void main(String[] args) {
MyInterface obj=new MyInterface() {
		@Override
		public void method() 
		{
			System.out.println("使用了匿名内部类");
		}
	};
		obj.method();
}

我们可以看到代码量大大的减少,我们直接在main中重写了接口中的抽象方法,然后通过接口的一个对象使用了它完成了任务。

结果

使用了匿名内部类

但是还可以进一步的简化,若对象也只用一次,比如上面的obj,那么可以通过匿名对象来使用匿名内部类。

public static void main(String[] args) {
	new MyInterface() {
			@Override
			public void method() 
			{
				System.out.println("匿名对象使用了匿名内部类");
			}
		}.method(); 
}

结果

匿名对象使用了匿名内部类

匿名内部类虽然好用但是只限于某些使用一次的方法,若某个方法要经常被使用,那么还是常规模式比较简单。

**

Lambda表达式

**
在编写代码的时候,总是有各种各样的重复的冗余的代码,真正有意义的代码往往很短,Lambda表达式删除了冗余。Lambda表达式起到的作用就像是加强版的匿名内部类。

Lambda表达式可以简单什么程度呢,我们先来看一下Lambda表达式的标准格式:

1.一些参数
2.一个箭头
3.一段代码

(参数列表)->{一些重写方法的代码};

()就是接口中抽象方法的参数列表
->就是传递的意思,把参数传递给方法体
{}是重写接口的抽象方法的方法体

可能你看到这个一头雾水,我们来举个例子,先定义一个类叫Player

public interface Player {

	public void play();
}

再定义一个局部方法来调用play函数

public static void invokePlayer(Player player) {
		player.play();
}

重点来了,我们在main函数中使用匿名内部类和Lambda表达式对比一下

public static void main(String[] args) {
new Player() 
		{
			@Override
			public void play() {
				System.out.println("打游戏");
			}
		}.play();//匿名内部类
}
	
invokePlayer(()->{
			System.out.println("打游戏");
		});//Lambda表达式

结果

打游戏
打游戏

我来解释一下,Lambda表达式就是删除代码的冗余。在使用匿名内部类时重写play方法是一件很繁琐的事情,那么我们只留下关键的代码部分,如我上面所说(再重复一遍):

**
1.()就是接口中抽象方法的参数列表(这里就是play方法,play方法没有参数,所以()留空

2.->就是传递的意思,把参数传递给方法体

3.{}是重写接口的抽象方法的方法体(方法体就是 System.out.println(“打游戏”);
**

上面的play方法是无参无返回值的方法,我们再来看一个有参有返回值的方法

定义一个简单Person类

public class Person {

	private String name;
	private int age;
	
	public Person(String name,int age) 
	{
		this.name=name;
		this.age=age;
	}
	public int getAge() 
	{
		return age;
	}
	
	@Override
	public String toString() 
	{
		return "姓名 "+name+"   年龄 "+age;
		
	}//方便输出
}

在main中使用Lambda表达式来排序(利用了Arrays类的sort方法)

public static void main(String[] args) {
Person[] array= {
			new Person("gfc",20),
			new Person("zbh",21),
			new Person("paco",22)
	};//创建一个Person数组
		
	Arrays.sort(array,(Person o1,Person o2)->{
		return o2.getAge()-o1.getAge();
	});//这个其实重写了sort的Compare方法,参数是Person o1,Person o2,返回值是o2.getAge()-o1.getAge(),按照年龄降序排列
	
	for(int i=0;i<array.length;i++) 
	{
		System.out.println(array[i]);
	}
}

结果

姓名 paco   年龄 22
姓名 zbh   年龄 21
姓名 gfc   年龄 20

我们看到带参带返回值与无参无返回值并没有太大的区别,但是有一点,Lambda表达式还可以更加简单,规则:

1.(参数列表):扩号中的参数类型可以不写

2.(参数列表):括号中的参数若只有一个,那么()与数据类型都可以不写

3.{方法体}:若代码只有一行,无论是否有返回值,那么{},return,分号都可以省略(三个要一起省略)

我们来按照这个规则看一下上面两个例子的简化版本

public static void main(String[] args) {
	invokePlayer(()->System.out.println("打游戏"));//只有一行代码
		
	Arrays.sort(array,(o1,o2)->o2.getAge()-o1.getAge());//只有一行代码且有参数
	for(int i=0;i<array.length;i++) 
	{
		System.out.println(array[i]);
	}
}

结果

打游戏
姓名 paco   年龄 22
姓名 zbh   年龄 21
姓名 gfc   年龄 20

以上就是这次日志的全部内容,大家再见啦!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值