JAVA面向对象四 内部内部类和lambda
面向对象马上也要进入尾声了,今天我们来学习下面向对象的最后部分,内部类和lamda。虽然我们可能会对面向只有一个模模糊糊的印象的,但我们只要多看多练,总会一层层揭开它神秘的面纱的。
内部类
内部类就是在类中在写一个类,根据所写类的位置和修饰,我们可以分为成员内部类,静态内部类,私有内部类,局部内部类,匿名内部类。相对来讲,匿名内部类是更重要一些的。
成员内部类
内部类作为外部类的成员,就称为成员内部类
成员内部类既有成员的特点,又有类的特点
可以成员修饰符进行修饰: 权限修饰符 static final.
类可以继承,实现…
定义:成员内部类中 除了静态常量,其他的静态内容不能定义。
使用:在成员内部类中可以直接使用外部类中的成员,包括私有的
使用内部类中的成员要通过内部类对象使用,包含私有的
其他类中使用内部类中的成员,需要**通过外部类对象构建内部类对象,**使用内部类的成员
(成员内部类可以直接使用外部类的成员,而外部类使用内部类的成员是需要调用内部类的对象的,如果是其他类,则需要通过调用外部类的对象构建内部对象使用。)
public class Outer01 {
//类中方法外->成员
public int i = 1;
private int j = 11;
//成员内部类
class Inner extends A{
//静态常量
static final int A = 5;
public int b = 15;
private int c = 20;
//成员方法
public void inner(){
System.out.println(i);
System.out.println(j);
}
}
//外部类的成员方法
public void outter(){
System.out.println(Inner.A);
//使用内部类中的成员要通过内部类对象使用
Inner in = new Inner();
System.out.println(in.b);
System.out.println(in.c);
in.inner();
}
}
私有内部类
在私有内部 类中可以直接使用外部类的成员,包含私有
在外部类中可以通过私有内部类的对象直接使用私有内部类的成员,包含私有
在其他类中无法使用私有内部类
可以间接使用私有内部类中的私有成员,可以作为外部类方法的参数返回
public class Outer03 {
//私有成员变量
private int i = 1;
//私有内部类
private class Inner{
//私有内部类的私有成员
private String a = "私有内部类的私有成员";
private void inner(){
System.out.println(i);
}
}
public String outer(){
Inner in = new Inner();
System.out.println(in.a);
in.inner();
return in.a;
}
}
静态内部类
静态内部类中定义静态内容,可以定义成员
在内部类中可以直接使用外部类中静态的内容,
如果想要使用外部类中成员的内容,通过外部类对象使用
(静态的可以直接调用静态的;静态调用成员需要构建对象才能调用。静态内部类也是一样的;)
public class Outer04 {
//静态变量
static int i = 1;
//成员变量
int j = 10;
//静态内部类
static class Inner{
static String a = "静态内部类中的静态变量a";
String b = "静态内部类中的成员变量b";
static void testStatic(){
System.out.println("静态内部类中的静态方法");
System.out.println(a);
System.out.println(new Inner().b);
System.out.println(i);
System.out.println(new Outer04().j);
}
void test(){
System.out.println("静态内部类中的成员方法");
System.out.println(i);
System.out.println(new Outer04().j);
System.out.println(a);
System.out.println(b);
}
}
}
局部内部类
只能在所定义的方法中使用
如果局部内部类中使用所在方法的参数,默认被final修饰
(java7手动添加final,java8之后默认final)
public class Outer05 {
static int a = 123;
public static void main(String[] args) {
//调用局部内部类,因为是在方法中的,需要调用outer方法
//静态方法调用局部方法需要构建对象,这边就创建Outer05的对象调用
Outer05 n = new Outer05();
n.outer(5);
}
void outer(final int args){
//局部
int i =1;
//局部内部类
class Inner{
//局部内部类成员变量
String str = "局部内部类成员变量";
void inner(){
System.out.println(i);
System.out.println(a);
System.out.println(args);
}
}
Inner in = new Inner();
System.out.println(in.str);
in.inner();
//args 作为局部内部类方法的参数,相当于被final修饰,不可以被改变
//args = 100;
}
}
匿名内部类
没有名字的内部类
public class Anonymous{
public static void main(String[] args) {
//第一种:只在当前行使用一次,后续无法继续使用
new Run(){
@Override
public void run() {
System.out.println("running");
}
}.run();
//第二种:引用指向匿名内部类对象,后续可以多次使用
Swim swim=new Swim(){
@Override
public void swimming() {
System.out.println("free swim");
}
@Override
public void drinking() {
System.out.println("drink water");
}
};
swim.drinking();
swim.swimming();
//第三种 匿名内部类做参数传递 调用方法
test(new Swim() {
@Override
public void swimming() {
System.out.println("free ~~~");
}
@Override
public void drinking() {
System.out.println("~~~~");
}
});
}
//一个静态带参的方法
static void test(Swim swim) {
swim.swimming();
swim.drinking();
}
}
//Run 接口
interface Run{
void run();
}
//Swim接口
interface Swim{
void swimming();
void drinking();
}
使用: 1>只在当前行使用一次,后续无法继续使用
//原本是需要创建一个类来实现对象的
class Tiger implements Run{
//重写接口的方法
@Override
public void run() {
System.out.println("running");
}
public static void main(String[] args) {
//运用接口的多态 所有有Run的对象
Run r=new Tiger();
r.run();
//现在如果只用run方法一次,不想要创建Tiger类,就可以用匿名了,直接用Run的对象
/*
new Run(){
//重写Run接口的方法
@Override
public void run() {
System.out.println("running");
}.run; //.run就是用run方法
}
*/
}
}
2>引用指向匿名内部类对象,后续可以多次使用
和第一种其实是一样的,就是加了一个变量接收第一种,这样就可以多次使用了。
//引用指向匿名内部类对象,后续可以多次使用
Run r =new Run(){
//重写Run接口的方法
@Override
public void run() {
System.out.println("running");
}
};
r.run;
如果只有一个接口方法的话,效果不是很明显,当有多个(可以看匿名内部类开始的代码)会非常便利,也提高了代码的复用性。
3>匿名内部类做参数传递
// 先写一个方法,然后直接调用使用一个带参的方法
/*test(第一种);
-------------------
test(new Run(){
//重写Run接口的方法
@Override
public void run() {
System.out.println("running");
});
*/
lambda
目的: 为了简化大量使用匿名内部类,可以java8提供的lambda表达式简化
前提: 函数型接口
函数型接口: 只要一个必须要被重写的抽象方法的接口
检查函数型接口的注解: @FunctionalInterface
语法:()->{}
(): 重写的抽象方法的参数列表
->: lambda符号,箭头符号
{}: 重写抽象方法的方法体{}
注意:
lambda体重写哪一个接口的抽象方法,看前面的引用
public static void main(String[] args) {
//匿名内部类
Run s = new Run() {
@Override
public void run() {
System.out.println("running");
}
};
//1.简化匿名内部类
//s是 Run s的,因为前面有定义Run s = new Run(){},所以这里没有写
s = ()->{
System.out.println("running。。。");
};
s.run();
//2.如果lambda中的方法体{}中语句体只有一句,前后的{}可以省略
//注意需要定义interface A的
A demo = ()->System.out.println("123");
//3.如果抽象方法的有形参,参数的数据类型可以省略
//注意需要定义interface B的
B demo = (x,y)-> System.out.println(x+y);
//4.如果抽象方法的有形参,并且参数只有一个,前后()可以省略
//注意需要定义interface C的
C demo = i-> System.out.println(i);
//5.如果语句体只有一句,并且是return语句
//注意需要定义interface D的
D demo = i-> {
return i>100;
};
到现在面向对象基本是结束了,但这也只是一些基础的语法点,要想熟练运用还有很长的路要走……一定要一直向前,不能停下前进的脚步。