- 代码块
静态代码块:有static修饰,属于类,与类一起优先加载,自动执行一次
实例代码块:无static修饰,属于对象,每次创建对象时,都会优先执行一次。
package com.itheima.code;import java.util.Arrays;public class CodeDemo1 {public static String schoolName;public static String[] cards = new String[3];//静态代码快:有static修饰,属于类,与类一起优先加载,自动执行一次//基本作用:可以完成对象的静态资源的初始化static{System.out.println("静态代码块执行了");schoolName = "黑马程序员";cards[0] = "大王";cards[1] = "小王";}public static void main(String[] args) {System.out.println("main方法执行了");System.out.println(schoolName);System.out.println(Arrays.toString(cards));} }
输出:
静态代码块执行了
main方法执行了
黑马程序员
[大王, 小王, null]package com.itheima.code;public class CodeDemo2 {private String name;private String[] direction = new String[4];//实例代码块:无static修饰,属于对象,每次创建对象时,都会优先执行一次。//基本作用:初始化对象的实例资源。{System.out.println("实例代码块执行了");name = "itheima";direction[0] = "N";direction[1] = "S";direction[2] = "E";direction[3] = "W";}public static void main(String[] args) {System.out.println("main方法执行了");new CodeDemo2();} }
输出:
main方法执行了
实例代码块执行了
- 成员内部类
成员内部类创建对象的格式:外部类名称.内部类名称 对象名 = new 外部类名称().内部类名称();
可以直接访问外部类的实例成员、静态成员
可以拿到当前外部类对象,格式是:外部类名.this。
package innerClass;public class Outer {public static String schoolName = "黑马";public static void test(){System.out.println("Outer.test()");}private int age;public void run(){}//成员内部类:无static修饰,属于外部类的对象持有public class Inner{public void show(){System.out.println("show");//成员内部类中可以直接访问外部类的静态成员System.out.println(schoolName);test();//也可以直接访问外部类的实例成员System.out.println(age);run();System.out.println(this);System.out.println(Outer.this);}} }
package innerClass;public class Test {//成员内部类创建对象的格式:// //外部类名称.内部类名称 对象名 = new 外部类名称().内部类名称();public static void main(String[] args) {Outer.Inner inner = new Outer().new Inner();inner.show();} } class People{private int heartBeat = 100;public class Heart{private int heartBeat = 80;public void show(){int heartBeat = 200;System.out.println(heartBeat);//200System.out.println(this.heartBeat);//80System.out.println(People.this.heartBeat);//100}} }
- 静态内部类
静态内部类:属于外部类本身持有
静态内部类中可以直接访问外部类的静态成员
静态内部类中不可以直接访问外部类的实例成员
创建格式:外部类名称.内部类名称 对象名 = new 外部类名称.内部类名称();
package Innerclass2;public class Outer {public static String schoolName ;private int age;//静态内部类:属于外部类本身持有public static class Inner{public void show(){//静态内部类中可以直接访问外部类的静态成员System.out.println(schoolName);//静态内部类中不可以直接访问外部类的实例成员//System.out.println(age);报错}} }
package Innerclass2;public class Test {public static void main(String[] args) {//创建格式:外部类名称.内部类名称 对象名 = new 外部类名称.内部类名称();Outer.Inner inner = new Outer.Inner();inner.show();} }
- 匿名内部类
匿名内部类实际上是有名字:外部类名$编号.class
匿名内部类本质是一个子类,同时会立即构建一个子类对象
package innerclass3;public abstract class Animal {public abstract void cry(); }
package innerclass3;public class Test {public static void main(String[] args) {//匿名内部类实际上是有名字:外部类名$编号.class//匿名内部类本质是一个子类,同时会立即构建一个子类对象Animal a = new Animal(){@Overridepublic void cry() {System.out.println("猫会喵喵喵叫");}};a.cry();} }
- 匿名内部类的常见使用形式:通常可以作为一个对象参数传输给方法使用
package innerclass3;public class Test2 {public static void main(String[] args) {//匿名内部类的使用形式:通常可以作为一个对象参数传输给方法使用Swim s1 = new Swim(){@Overridepublic void swim() {System.out.println("学生游泳慢");}};start(s1);start(new Swim() {@Overridepublic void swim() {System.out.println("老师游泳快");}});}public static void start(Swim s){System.out.println("开始");s.swim();System.out.println("结束");} } interface Swim{void swim(); }
- 匿名内部类使用场景
package innerclass3;import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;public class Test3 {//需求:创建一个登录窗口,窗口上只有一个登录按钮public static void main(String[] args) {JFrame win = new JFrame("登录窗口");win.setSize(400,300);win.setLocationRelativeTo(null);//居中显示win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//退出程序JPanel panel = new JPanel();win.add( panel);JButton btn = new JButton("登录");panel.add(btn);//java要求必须给这个按钮添加一个点击事件监听器对象,这样就可以监听用户的点击操作,就可以做出反应。btn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("点击了登录按钮");}});win.setVisible(true);} }
- 使用comparator接口的匿名内部类实现对数组进行排序
package innerclass3;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;@Data @NoArgsConstructor @AllArgsConstructor public class Student {//姓名 年龄 private String name;private int age; }
package innerclass3;import java.util.Arrays; import java.util.Comparator;public class Test4 {public static void main(String[] args) {Student[] students = new Student[3];students[0] = new Student("张三", 18);students[1] = new Student("李四", 17);students[2] = new Student("王五", 19);//按照年龄从大到小排序Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o2.getAge() - o1.getAge();}});for (Student student : students){System.out.println(student.getName() + " " + student.getAge());}} }
- Lambda的认识
Lambda只能简化函数式接口的匿名内部类
写法:(被重写方法的形参列表)->{被重写方法的方法体代码。}
package lambda; //Lambda只能简化函数式接口的匿名内部类 //写法:(被重写方法的形参列表)->{被重写方法的方法体代码。} public class LambdaDemo1 {public static void main(String[] args) {Swim s = new Swim() {@Overridepublic void swimming() {System.out.println("我要开始游泳了");}};s.swimming();Swim s1 = () -> {System.out.println("我要开始游泳了");};s1.swimming();} } //函数式接口:只有一个抽象方法的接口。 @FunctionalInterface//声明函数式接口的注解。 interface Swim{void swimming(); }
- Lambda的省略规则:用于进一步简化Lambda表达式的写法。
- 参数类型全部可以省略不写。
- 如果只有一个参数,参数类型省略的同时“()”也可以省略,但多个参数不能省略“()”
- 如果Lambda表达式中只有一行代码,大括号可以不写,同时要省略分号“;”如果这行代码是return语句,也必须去掉return。
//按照年龄从大到小排序 // Arrays.sort(students, new Comparator<Student>() { // @Override // public int compare(Student o1, Student o2) { // return o2.getAge() - o1.getAge();//按照年龄降序 // } // });// Arrays.sort(students, (Student o1, Student o2) -> { // return o2.getAge() - o1.getAge(); // });// Arrays.sort(students, ( o1, o2) -> { // return o2.getAge() - o1.getAge(); // });Arrays.sort(students, (o1, o2) ->o2.getAge() - o1.getAge());
静态方法引用:类名::静态方法名
package innerclass3;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;@Data @NoArgsConstructor @AllArgsConstructor public class Student {//姓名 年龄private String name;private int age;public static int compareByAge(Student s1,Student s2){return s2.getAge() - s1.getAge();} }
//按照年龄从大到小排序// Arrays.sort(students, (o1, o2) -> // o2.getAge() - o1.getAge() // );//静态方法引用:类名::静态方法名Arrays.sort(students, Student::compareByAge);
实例方法引用:对象名::实例方法
package innerclass3;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;@Data @NoArgsConstructor @AllArgsConstructor public class Student {//姓名 年龄private String name;private int age;private double score;//静态方法public static int compareByAge(Student s1,Student s2){return s2.getAge() - s1.getAge();}//实例方法public int compareByScore(Student s1,Student s2){return Double.compare(s2.getScore(),s1.getScore());} }
//静态方法引用:类名::静态方法名Arrays.sort(students, Student::compareByAge);//实例方法引用:对象名::实例方法Student t = new Student();Arrays.sort(students, t::compareByScore);
- 特定类的方法引用:类型名称::方法名
- 使用场景:如果某个Lambda表达式里只是调用一个特定类型的实例方法,并且前面参数中的第一个参数作为方法的主调,后面的所有参数都是作为改实例方法的入参,则此时就可以使用特定类型的方法引用。
package lambda;import java.util.Arrays;public class ddemo {public static void main(String[] args) {String[] names = {"Tom","Jerry","angle","Andy"};//忽略大小写,进行升序排列Arrays.sort(names,(s1,s2) -> s1.compareToIgnoreCase(s2));//特定类型方法引用:类型名称::方法名Arrays.sort(names,String::compareToIgnoreCase);System.out.println(Arrays.toString(names));} }
- 构造器引用:类名::new
- 使用场景:如果某个Lambda表达式里只是在创建对象,并且“->”前后参数情况一致,就可以使用构造器引用。