内部类与成员外部类的关系
a.成员内部类的创建需要依赖于外部类对象-(成员方法必须通过对象调用),在没有外部类实例之前无法创建成员内部类对象
b.内部类与外部类相对独立,不是is a 的关系(发动机-汽车)
c.私有属性的互相访问,内部类可以直接访问外部类,而外部类访问内部类需要内部类的对象来访问
d.创建内部类的语法
1.在外部类内部创建内部类对象(Inner inner = new Inner())
2.在外部类外部创建内部类对象,外部类.内部类 inner = new Outter().new Inner();
e.在内部类内部使用隐藏的外部类对象(隐藏的this)
成员内部类的实例化:
成员内部类:类比成员方法,不能拥有静态域但是可以访问外部类的静态域
2.静态内部类
定义在外部类的内部,使用static修饰,类比静态方法,静态内部类不需要外部类对象产生就能使用。
不能访问外部类的成员域,但能访问静态域
静态内部类的创建语法:
1.外部类内部:与成员内部类一样
2.外部类外部:StaticInnerClass.Inner inner = new StaticInnerClass.Inner();
3.方法内部类
定义在方法内部:类比局部变量
a.对外部完全隐藏,因此方法内部类不能有任何访问修饰符
b.方法内部类没有访问形参是,这个形参是可以在方法中随意修改的,一旦方法内部类中使用了形参,这个形参必须被声明为final。
4.匿名内部类
a.必须继承一个抽象类或者实现一个接口
b.没有构造方法
通常一个接口实现类,实现接口的方法:
匿名内部类:(代码中有两种实现方式,上面一个实现类是一般接口实现类的运用)
总结:
本质上是一个没有名字的局部内部类,定义在方法中、代码块中、等。
作用:方便创建子类对象,最终目的是为了简化代码编写。
格式:(创建一个匿名内部类对象)
new 类|抽象类名|或者接口名(){
重写方法;
}
特点:
匿名内部类是一个没有名字的内部类。
匿名内部类写出来就会产生一个匿名内部类的对象。
匿名内部类的对象类型相当于是当前new的那个的接口类型的子类型。
举个例子:
/**
目标:掌握匿名内部类的使用形式
*/
public class Test {
public static void main(String[] args) {
//使用匿名内部类替代学生类,创建的类型是new的那个类的子类
Swimming s = new Swimming() {
@Override
public void Swim() {
System.out.println("学生游的很快");
}
};
go(s);
}
/**
方法:学生、老师、运动员可以一起游泳
*/
public static void go(Swimming s)
{
System.out.println("开始游泳了~~");
s.Swim();
System.out.println("结束游泳了~~");
}
}
//创建学生类
/*class Student implements Swimming{
@Override
public void Swim() {
System.out.println("学生游的很快");
}
}*/
//定义一个接口规范游泳
interface Swimming{
void Swim();
}
匿名内部类的好处是可以直接new 接口{接口中声明的抽象方法(重写)}
2.lambda表达式
举个例子:
01.创建一个新的线程,指定线程要执行的任务
public static void main(String[] args) {
// 开启一个新的线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("新线程中执行的代码 :
"+Thread.currentThread().getName());
}
}).start();
System.out.println("主线程中的代码:" + Thread.currentThread().getName());
}
代码分析:
02.Lambda表达式初体验
Lambda表达式是一个匿名函数,可以理解为一段可以传递的代码
Lambda表达式的优点:
1.简化了匿名内部类的使用,语法更加简单。
2.匿名内部类语法冗余,体验了Lambda表达式后,发现Lambda表达式是简化匿名内部类的一种方式。
new Thread(() -> { System.out.println("新线程Lambda表达式..."
+Thread.currentThread().getName()); })
.start();
03.Lambda的语法规则
Lambda省去了面向对象的条条框框,Lambda的标准格式由3个部分组成:
格式说明:
(参数类型 参数名称) -> {
代码体;
}
01.(参数类型 参数名称):参数列表
02.{代码体;} :方法体
03.-> : 箭头,分割参数列表和方法体
04.两种Lambda(此时的运用的接口都是作为方法的参数)
1.无参无返回值:
定义一个接口:
public interface UserService {
void show();//接口中的抽象方法没有参数
}
然后创建主方法使用:
public class Demo03Lambda {
public static void main(String[] args) {
goShow(new UserService() {
@Override
public void show() {
System.out.println("show 方法执行了...");//此处是打印语句,无返回值
}
});
System.out.println("----------");
goShow(() -> { System.out.println("Lambda show 方法执行了..."); });
}
public static void goShow(UserService userService){
userService.show();
}
}
2.有参有返回值的
创建一个Person对象
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private String name;
private Integer age;
private Integer height;
}
然后我们在List集合中保存多个Person对象,然后对这些对象做根据age排序操作
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Person("周杰伦",33,175));
list.add(new Person("刘德华",43,185));
list.add(new Person("周星驰",38,177));
list.add(new Person("郭富城",23,170));
Collections.sort(list, new Comparator<Person>() {//这个是java
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});
for (Person person : list) {
System.out.println(person);
}
}
我们发现在sort方法的第二个参数是一个Comparator接口的匿名内部类,且执行的方法有参数和返回值,那么我们可以改写为Lambda表达式
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Person("周杰伦",33,175));
list.add(new Person("刘德华",43,185));
list.add(new Person("周星驰",38,177));
list.add(new Person("郭富城",23,170));
/*Collections.sort(list, new Comparator() {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();
}
});
for (Person person : list) {
System.out.println(person);
}*/
System.out.println("------");
Collections.sort(list,(Person o1,Person o2) -> {//这里的lambda表达式,有参数,有返回值,返回值直接用return
return o1.getAge() - o2.getAge();
});
for (Person person : list) {
System.out.println(person);
}
}
Lambda表达式的省略写法
public class Demo05Lambda {
public static void main(String[] args) {
goStudent((String name,Integer age)->{
return name+age+" 6666 ...";
});
// 省略写法
goStudent((name,age)-> name+age+" 6666 ...");
System.out.println("------");
goOrder((String name)->{
System.out.println("--->" + name);
return 666;
});
// 省略写法
goOrder(name -> {
System.out.println("--->" + name);
return 666;
});
goOrder(name -> 666);
}
public static void goStudent(StudentService studentService){
studentService.show("张三",22);
}
public static void goOrder(OrderService orderService){
orderService.show("李四");
}
}
Lambda表达式的使用前提:
1.具体去实现的方法(在类中先去声明这种方法、)的参数或局部变量类型必须为接口才能使用Lambda
2. 方法中用的接口中有且仅有一个抽象方法(@FunctionalInterface)
lambda表达式和匿名内部类的区别: