Final关键字 认识final final 关键字是最终的意思,可以修饰:类,方法,变量
修饰类:该类被称为最终类,特点是不能被继承了
修饰方法:该方法被成为最终方法,特点是不能被重写了
修饰变量:该变量有且只能被赋值一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package life.eabor.finaldemo; public class FinalDemo1 { public static final String NAME = "eabor" ; public static void main (String[] args) { final int NUMBER = 666 ; } } final class A {} class C { public void m1 () { System.out.println("m1" ); } } class D extends C { }
final 修饰变量的注意
final修饰的基本类型变量,变量储存的数据 不能被改变
final修饰的引用类型变量,变量存储的地址 不能被改变,但是地址所指向对象的内容是可以被改变的
1 2 3 4 5 6 7 final int a = 20 ;final int [] arr = {};arr[index] = num;
常量
使用 static final 修饰的成员变量就被称为常量
作用:常用于记录系统的配置信息
常量命名规范:建议大写英文单词,多个单词使用下划线连接
1 2 public class Constant public static final USER_NAME = "Eabor" ;
使用常量记录系统配置信息的优势、执行原理
代码的可读性更好,可维护性更好
程序编译后,常量会被”宏替换“:出现常量的地方全部会被替换成其记住的字面量,这样可以保证使用常量和直接使用字面量的性能是一样的
单例类(设计模式) 什么是设计模式
一个问题通常有 种解法,其中肯定有一种解法是最优的,这种最优的解法被总结出来了,称为设计模式
设计模式有 多种,对应 多种软件开发中会遇到的问题
单例设计模式
写法,实现步骤
把类的构造器私有化
定义一个类变量记住类的一个对象
定义一个类方法,返回对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class A { private static A a = new A (); private A () { } public static A getObject () { return a; } }
懒汉式单例类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class B { private static B b; private b () { } public static B getObject () { if (b == null ){ b = new B (); } return b; } }
枚举类 枚举类式一种特殊类
枚举类的写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 修饰符 enum 枚举类名{ 名称1 ,名称2 ,...; 其他成员... } public enum A { X,Y,Z; } public class Text { public static void main (String[] args) { A a1 = new X ; A a2 = new Y ; System.out.println(a1.name()); System.out.println(a2.name()); System.out.println(a1.ordinal); System.out.println(a2.ordinal); } }
枚举类的常见应用场景
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class Text { public static void main (String[] args) { move(Direction.Dowm); } public static void move (Direction direction) { switch (direction){ case UP : ... break ; case DOWN : ... break ; case LEFT : ... break ; case ROGHT : ... break ; } } public enum Direction { UP,DOWN,LEFT,RIGHT; }
抽象类
在 中有一个关键字:abstract ,他就是抽象类的意思,可以用来修饰类,成员方法
abstract 修饰类,这个类就是抽象类
abstract 修饰方法,这个方法就是抽象方法
1 2 3 修饰符 abstract class 类名{ 修饰符 abstract 返回值类型 方法名称(形参列表); }
1 2 3 4 public abstract class A { public abstract void test () ; }
抽象类的注意事项、特点:
抽象类中不一定要有抽象方法,有抽象方法的类必须是抽象类
类有的成员:成员变量,方法,构造器,抽象类都可以有
抽象类最主要的特点 :抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现
一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类
抽象类的好处 父类知道每个子类都要做的某个行为,但是每个子类要做的情况不一样,父类就定义成抽象方法,交给子类去重写实现,我们设计这样的抽象类,就是为了更好的支持多态
模板方法设计模式 提供一个方法作为完成某类功能的模板,模板方法封装了每个实现步骤,但允许子类提供特定步骤实现
写法
定义一个抽象类
在里面定义两个方法
一个是模板方法(建议使用 修饰):把共同的实现步骤放里面去
一个是抽象方法:不确定的实现步骤,交给具体的子类来完成
接口 提供了一个关键字 定义出接口
1 2 3 4 public interface 接口名 { }
常量: 接口中定义的常量可以省略 不写,默认会加上去
抽象方法: 接口中定义的抽象方法可以省略 不写,默认会加上去
注意抽象类不能创建对象
接口是用来被类实现(implements)的 ,实现接口的类称为实现类 ,一个类可以实现多个 接口
1 2 3 修饰符 class 实现类类名 implements 接口1 , 接口2 , 接口3 ,... { }
接口的好处
弥补了单继承的不足,一个类可以实现多个接口,使类的角色更多,功能更强大
让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现(利于程序的解耦合)
JDK 8开始,接口新增了三种形式的方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public interface A { default void text1 () { ... } private void text2 () { ... } static void text3 () { ... } }
接口的注意事项
接口与接口可以多继承:一个接口可以同时继承多个接口(重点)
一个接口可以继承多个接口,如果多个接口存在方法签名冲突,则此时不支持多继承,也不支持多实现
一个类继承了父类,又同时实现了接口,如果父类中和接口中有同名的默认方法,则实现类会优先调用父类的
一个类实现了多个接口,如果多个接口中存在同名的默认方法,可以不冲突。这个类重写该方法即可
抽象类、接口的区别对比 相同点:
都是抽象形式,都可以有抽象方法,都不能创建对象
都是派生子类模式:抽象类是被子类继承使用,接口被实现类实现
一个类继承抽象类,或实现接口,都必须重写完他们的抽象方法,否则自己要成为抽象类或报错
都能支持多态,都能实现解耦合
不同点
抽象类中可以定义类的全部成员,接口只能实现定义常量,抽象方法(JDK8新增的三种方式)
抽象类只能被类单继承,接口可以被类多实现
一个类继承抽象类就不能再继承其他类,一个类实现了接口(还可以继承其他类或者实现其他接口)
抽象类体现模板思想:更利于做父类,实现代码的复用性
接口更适合做功能的解耦合,解耦合性更强更灵活
代码块 代码块是类的五大成分之一(成员变量、构造器、方法、代码块、内部类)
代码块分两种:
静态代码块:属于类
格式:static{}
特点:类加载时自动执行,由于类只会加载一次,所以静态代码块也会执行一次
作用:完成类的初始化,例如:对静态变量的初始化赋值
实例代码块:
格式:{}
特点:每次创建对象时,执行实例代码块,并在构造器前执行
作用:和构造器一样,都是用来完成对象初始化的,例如:对实例变量进行初始化赋值
内部类 如果一个类定义在另一个类的内部,这个类就是内部类 场景: 当一个类的内部,包含了一个完整的事物,且这个事物没有必要单独设计时,就可以把这个事物设计成内部类
1 2 3 4 5 public class A { public class B { } }
成员内部类 就是类中的一个普通成员,类似前面我们学过的成员变量,成员方法
1 2 3 4 5 6 7 8 main{ Outer.Inner oi = new Outer ().new Inner (); }
1 2 3 4 5 6 public class Outer { public class Inner { } }
静态内部类 有static修饰的内部类,属于外部类自己持有
1 2 3 4 5 6 public class Outer { public static class Inner { } }
1 2 3 4 5 6 main{ 外部类名.内部类名 对象名 = new 外部类.内部类(); Outer.Inner in = new Outer .Inner(); }
局部内部类局部内部类是定义在方法中、代码块中、构造器等执行体中
匿名内部类 是一种特殊的局部内部类 所谓匿名:指的是程序员不需要为这个类声明名字,默认有一个隐藏的名字
1 2 3 new 类或接口(参数值...){ 类体(一般是方法重写); };
1 2 3 4 5 new A (){ @Override public void cry () { } };
特点: 匿名内部类本质就是一个子类,并会立即创建出一个子类对象作用: 用于更方便的创建一个子类对象
常见使用形式
通常作为一个对象参数传输给方法
需求:学生老师要参加游泳比赛
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class Text { public static void main (String[] args) { start(new Swim () { @Override public void swim () { System.out.println("老师开始游泳" ); } }); start(new Swim () { @Override public void swim () { System.out.println("学生开始游泳" ); } }); } public static void start (Swim s) { System.out.println("game start" ); s.swim(); System.out.println("game end" ); } interface Swim { void swim () ; } }
使用场景 调用别人提供的方法实现需求时,这个方法正好可以让我们传输一个匿名内部类对象给其使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class Test2 { public static void main (String[] args) { JFrame win = new JFrame ("登录窗口" ); win.setSize(300 , 200 ); win.setLocationRelativeTo(null ); win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel panel = new JPanel (); win.add(panel); JButton btn = new JButton ("登录" ); win.add(btn); btn.addActionListener(e -> System.out.println("用户点击了登录按钮" )); btn.addActionListener(new ActionListener () { @Override public void actionPerformed (ActionEvent e) { System.out.println("用户点击了登录按钮" ); } }); win.setVisible(true ); } }
eg. 使用comparetor接口的匿名内部类实现对数组进行排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package life.eabor.innerclass; import java.util.Arrays; import java.util.Comparator; public class Text3 { public static void main (String[] args) { Student[] s = new Student [6 ]; s[0 ] = new Student ("李long" , 19 , '女' ); s[1 ] = new Student ("张三" , 18 , '男' ); s[2 ] = new Student ("李四" , 19 , '女' ); s[3 ] = new Student ("王五" , 20 , '男' ); s[4 ] = new Student ("赵六" , 21 , '女' ); s[5 ] = new Student ("钱七" , 22 , '男' ); Arrays.sort(s, new Comparator <Student>() { @Override public int compare (Student o1, Student o2) { if (o1.getAge() > o2.getAge()){ return 1 ; }else if (o1.getAge() < o2.getAge()){ return -1 ; } return 0 ; return o1.getAge() - o2.getAge(); } }); for (Student student : s){ if (student != null ){ System.out.println(student); } } } }
函数式编程 此“函数”类似于数学中的函数(强调做什么),只要输入的数据一直返回的结果也是一致 Java中的函数(Lambda表达式):(x) -> 2x+1
函数式编程解决了: 使用Lambda函数替代某些匿名内部类对象,从而让代码更简洁,可读性更好
Lambda
JDK 8 开始新增的一种语法,他表示函数
可以用于替代某些匿名内部类对象,让程序更简洁,可读性更好
1 2 3 (被重写方法的形参列表)->{ 被重写方法的方法体代码 }
注意:Lambda表达式只能替代函数式接口的匿名内部类
什么是函数式接口:有且只有一个抽象方法接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package life.eabor.lambda; public class Text { public static void main (String[] args) { Swimmer swimmer = () -> { System.out.println("I am swimming" ); }; swimmer.swim(); } } @FunctionalInterface interface Swimmer { void swim () ; }
Lambda表达式的省略规则 作用:用于进一步简化Lambda表达式的写法
具体规则:
参数类型全部可以省略不写
如果只有一个参数的同时”()”也可以省略,但多个参数不能省略
如果Lambda表达式中只有一行代码,大括号可以不写,同时要省略”;”,如果这行代码是return语句,也必须去掉return
1 Arrays.sort(s, (o1, o2)->o1.getAge() - o2.getAge());
方法引用 静态方法引用: 类名::静态方法 使用场景 如果某个Lambda表达式里只是调用一个静态方法,并且”->”前后参数的形式一致,就可以使用静态方法引用
1 2 3 4 5 6 7 8 Arrays.sort(s, Student::compareByAge); Student{ ..... public static int compareByAge (Student s1, Student s2) { return s1.getAge() - s2.getAge(); } }
实例方法引用: 类名::实例方法 使用场景 如果某个Lambda表达式里只是调用一个实例方法,并且”->”前后参数的形式一致,就可以使用实例方法引用
特定类型的方法引用 特定类的名称::方法 使用场景 如果某个Lambda表达式里只是调用一个特定类型的实例方法,并且前面参数列表中第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参是,则此时就可以使用特定类型的方法引用
1 Arrays.sort(names, String::compareToIgmoreCase)
构造器引用 类名::new 使用场景 如果某个Lambda表达式里只是在创建对象,并且”->”前后参数的形式一致,就可以使用构造器引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package life.eabor.method1reference; public class Demo2 { public static void main (String[] args) { CarFactory cf = Car::new ; Car c = cf.getCar("保时捷" ); System.out.println(c); } } @FunctionalInterface interface CarFactory { Car getCar (String name) ; } class Car { private String name; public Car () { } public Car (String name) { this .name = name; } public String getName () { return name; } public void setName (String name) { this .name = name; } @Override public String toString () { return "Car{" + "name='" + name + '\'' + '}' ; } }
常用API String String代表字符串,它的对象可以封装字符串数据,并提供了很多方法完成对字符串的处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package life.eabor.stringdemo; public class StringDemo1 { public static void main (String[] args) { String s1 = "Hello World" ; System.out.println(s1); System.out.println(s1.length()); String s2 = new String (); System.out.println(s2); String s3 = new String ("Hello World" ); System.out.println(s3); char [] chars = {'H' , 'e' , 'l' , 'l' , 'o' , ' ' , 'W' , 'o' , 'r' , 'l' , 'd' }; String s4 = new String (chars); System.out.println(s4); byte [] bytes = {72 , 101 , 108 , 108 , 111 , 32 , 87 , 111 , 114 , 108 , 100 }; String s5 = new String (bytes); System.out.println(s5); } }
只要是以“…”方式写出的字符串对象,会存储到字符串常量池且相同内容的字符串只存储一份 通过new方式创建字符串对象,每new一次都会产生一个新的对象放在堆内存中
ArrayList 集合是一种容器,用来装数据的,类似于数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package life.eabor.arraylist; import java.util.ArrayList; public class ArrayListDemo1 { public static void main (String[] args) { ArrayList<String> list = new ArrayList <>(); list.add("Hello" ); list.add("World" ); list.add("Java" ); for (int i = 0 ; i < list.size(); i++) { System.out.println(list.get(i)); } list.remove(1 ); list.remove("Java" ); list.set(0 , "Hello World" ); } }
GUI 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package life.eabor.GUI; import javax.swing.*; public class Demo { public static void main (String[] args) { JFrame jf = new JFrame ("Log in" ); JPanel jp = new JPanel (); jf.add(jp); jf.setSize(400 , 300 ); jf.setLocationRelativeTo(null ); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JButton JB = new JButton ("登录" ); jp.add(JB); jf.setVisible(true ); } }
[[加强]]