目录
一. 接口
1. 接口的定义
2. 接口的实现
3. Comparable接口
4. 抽象类和接口的区别
小结
二. static关键字
1. 静态成员变量
2. static 静态方法
3. static静态代码块
格式:
作用:
执行顺序:
三. 接口拓展
default 和 static
一. 接口
如果一个抽象类没有字段(成员变量),并且所有方法全部都是抽象方法。在这种场景下,就可以把该抽象类定义为interface接口。所谓interface接口,就是比抽象类还要更佳抽象的一种纯抽象的代码结构。因为它连字段(成员变量)都不能存在,只能包含常量、抽象方法、默认方法等。
1. 接口的定义
类--- class 接口--- interface
接口定义语法规则:
修饰符 interface I接口名{1.抽象方法:public abstrcat 返回值类型 方法名();其中public abstrcat可以省略2.静态常量:public static final 数据类型 常量名=值;其中public static final可以省略 }
[注]:
●接口中的所有的修饰符均是public
●常量自带 public static final
double PI = 3.14;//常量 有默认修饰符 变量不可存在
●方法自带 public abstrcat
void draw();void aaa();
●不能有构造方法
//不能有构造方法//Interfaces cannot have constructorspublic IShape() {}
●不能存在普通的方法
//不能存在普通的方法//Abstract methods do not specify a bodypublic void doSth() {System.out.println("doSth");}
●常量不能重新赋值
System.out.println(is1.PI); // The final field IShape.PI cannot be assignedis1.PI=777;//常量不能重新赋值
2. 接口的实现
当一个具体的class去实现一个interface时,需要使用implements关键字。
接口实现语法规则:
//类实现接口 修饰符 class 类名 implents 接口名{}
示例:
IShape接口:
public interface IShape {double PI = 3.14;//常量 有默认修饰符 变量不可存在void draw();void aaa(); }
子类:
//实现类必须要实现接口中的所有的抽象方法,除非此类是抽象类 public class Flower implements IShape {@Overridepublic void draw() {System.out.println("❀");}@Overridepublic void aaa() {System.out.println("flower --- aaa");}}
//抽象类实现接口 可以不实现抽象方法 abstract class Star implements IShape {}
[注]:
●接口和抽象类均不能实例化
//Cannot instantiate the type IShapeIShape is = new IShape();//接口和抽象类均不能实例化
●面向抽象设计
接口 对象名= new 实现类()
//面向抽象设计IShape is1 = new Flower();is1.draw();// ❀
3. Comparable接口
Comparable接口用于进行对象之间的比较,主要用于排序方法。
public class Student implements Comparable {private String name;private int score;public Student(String name, int score) {super();this.name = name;this.score = score;}@Overridepublic String toString() {return "[name=" + name + ",score=" + score + "]";}//实现Comparable接口的compareTo()方法// ==0 不交换// >0 如果希望当前对象排在参数后面,返回大于0的// <0 如果希望当前对象排在参数前面,返回小于0的@Overridepublic int compareTo(Object o) {if (o instanceof Student) {Student s = (Student) o;if (this.score == s.score) {return 0;} else if (this.score > s.score) {return -1;} else {return 1;}}return 0;}}
测试:
public class Demo01 {public static void main(String[] args) {Student[] students = new Student[] { new Student("zkt1", 77), new Student("zkt2", 88),new Student("zkt3", 99) };// 给学生数组排序 // Arrays.sort(students);sort(students);System.out.println(Arrays.toString(students));}public static void sort(Comparable[] array) {for (int i = 0; i < array.length - 1; i++) {for (int j = 0; j < array.length - 1 - i; j++) {if (array[j].compareTo(array[j + 1]) > 0) {Comparable c1 = array[j];array[j] = array[j + 1];array[j + 1] = c1;}}}} }
运行结果:
4. 抽象类和接口的区别
abstract class 抽象类
interface接口 定义
使用 abstract class关键字定义抽象类
使用 interface关键字定义接口
继承
只能extends继承一个class类
可以implements多个interface接口
并且接口之间直接允许多重extends继承字段(成员变量)
可以定义实例字段(成员变量)
不能定义实例字段(成员变量)
常量
使用static final关键字定义常量
无需任何关键字,只能定义常量
抽象方法
可以定义抽象方法
可以定义抽象方法
非抽象方法
可以定义非抽象方法(普通方法)
可以定义default方法
构造方法
可以有构造方法
不允许有构造方法
访问修饰符
可以使用任意访问修饰符
只能使用public访问修饰符
小结
●Java的接口(interface)用于定义纯粹的抽象行为(方法)规范。
●一个类只能extends继承自另一个类(单继承)。但是,一个类可以implements实现多个interface接口(多重实现)。
●一个interface可以继承自多个interface(接口之间允许多重继承)。
●一个类实现interface接口时,要求必须实现该接口中所有的抽象方法。
●接口也是一种“高层”的数据类型,可以用于定义“引用”的类型,也适用于"向上转型"和"向下转型"。
●接口不允许实例化。
●接口的所有方法都是抽象方法,接口不能定义实例字段(成员变量)。
●接口可以定义default方法(JDK版本 >= 1.8),default方法可以包含方法体。
●实现Comparable接口的类,该类的对象之间可以进行“比较”,用于“排序”。
二. static关键字
1. 静态成员变量
在一个class类中定义的成员变量,我们称之为实例成员变量(成员变量)。实例成员变量的特点是,每个实例都有独立的成员变量,各个实例的同名成员变量互不影响。除此以外,还有一种成员变量,是使用static关键字修饰的成员变量,称为静态成员变量:static field。
实例成员变量在每个实例中都有自己的一个独立“空间”,但是静态成员变量只有一个共享“空间”,所有实例都会共享该成员变量。示例:
Person类:
public class Person {// 实例成员变量private String name;private int age;// 静态成员变量public static String school;public Person(String name, int age) {super();this.name = name;this.age = age;}
测试类:
Person p1 = new Person("zkt1", 21);Person p2 = new Person("zk2", 22);//静态成员变量访问方式://1.对象名.成员变量名//2.类名.静态变量名//成员变量被static修饰,此字段从对象级别提升到类级别//改类的所有的对象共享改字段的值p1.school = "清华大学";// 不推荐System.out.println(p1.school);p2.school = "浙江大学";System.out.println(p1.school);System.out.println(p2.school);System.out.println(Person.school);// 推荐
静态成员变量访问方式:
对象名.成员变量名类名.静态变量名 --- 推荐
[注]:
●成员变量被static修饰,此字段从对象级别提升到类级别
●改类的所有的对象共享改字段的值
对于静态成员变量,无论修改哪个实例的静态成员变量,都是访问相同的内存空间:所有实例的静员态成员变量都被修改了,原因是静态成员变量并不属于实例。
内存情况:
class Person {public String name;public int age;// 定义静态成员变量number:public static int number;public Person(String name, int age) {this.name = name;this.age = age;} }
public class Main {public static void main(String[] args) {Person ming = new Person("Xiao Ming", 12);Person hong = new Person("Xiao Hong", 15);ming.number = 88;System.out.println(hong.number);hong.number = 99;System.out.println(ming.number);} }
2. static 静态方法
static修饰的方法称为静态方法。调用实例方法必须通过一个实例对象,而调用静态方法则不需要实例对象,通过类名就可以调用。
细节:
●如果一个方法被static所修饰,此方法为静态方法
●静态方法属于class类级别的,而不属于实例对象。因此,静态方法内部,不能访问非静态的成员变量,也不能出现this关键字
// 如果一个方法被static所修饰,此方法为静态方法// 类名.方法名()推荐 对象名.方法名()不推荐public static void eat() {// 不能访问非静态的成员变量,也不能出现this关键字// System.out.println(name );System.out.println("你好 要吃饭了");System.out.println(school);sleep();}public static void sleep() {System.out.println("睡觉的办法");}
●普通方法可以访问静态方法和非静态方法
// 普通方法可以访问静态方法和非静态方法public void doSth() {eat();getName();}
静态方法调用:
类名.方法名()推荐 对象名.方法名()不推荐
Person p1 = new Person("zkt1", 21); //静态方法调用--推荐类名.方法名()Person.eat();
3. static静态代码块
在Java类中使用static关键字和{}声明的静态代码块,静态代码块在“类被加载”的时候运行,而且只运行一次,并且优先于各种代码块以及构造函数。如果一个类中有多个静态代码块,会按照书写顺序依次执行。
格式:
public class CodeBlock {static{System.out.println("静态代码块");} }
作用:
如果有些代码逻辑或对象,需要在项目启动的时候就执行或创建,这时候就需要静态代码块。比如一个项目启动需要加载的很多配置文件或者数据库连接池对象等,我们就可以都放入静态代码块中。
另外,静态代码块中,只允许调用静态方法或静态的成员变量,不允许调用普通方法或普通成员变量。class CodeBlock {// 静态成员变量public static int value;static {System.out.println("静态代码块A");register(); // 仅允许调用静态方法// sayHello(); // 不允许调用普通方法// 允许使用静态成员变量(但是,需要在这个静态代码块之前先定义,再使用)value += 10; }// 静态方法public static void register(){System.out.println("CodeBlock类的静态方法register()");}// 普通方法public void sayHello() {System.out.println("普通方法");} }
执行顺序:
●静态代码块>构造代码块>构造方法
●先父类再子类,先静态后非静态
●父静态 子静态 父构造 父构造方法 子构造 子构造方法
Fu类:
public class Fu {public Fu() {System.out.println("这个是父类的无参构造方法");}{System.out.println("这个是父类的代码块1");}{System.out.println("这个是父类的代码块2");}static {System.out.println("这个是父类的静态代码块1");}static {System.out.println("这个是父类的静态代码块2");} }
Zi类:
public class Zi {public Zi() {System.out.println("这个是子类的无参构造方法");}{System.out.println("这个是子类的代码块1");}{System.out.println("这个是子类的代码块2");}static {System.out.println("这个是子类的静态代码块1");}static {System.out.println("这个是子类的静态代码块2");} }
测试:
Fu fu = new Fu();System.out.println("===============");Fu fu1 = new Fu();System.out.println("***************");Zi zi = new Zi();System.out.println("===============");Zi zi1 = new Zi();
运行结果:
●静态代码块随着类的加载而加载,只加载1次
●构造代码块随着对象的创建而调用,对象创建几次,调用几次
三. 接口拓展
default 和 static
在JDK 1.8及其更高版本中,接口中可以定义default 和 static方法。
IAAA接口:
public interface IAAA {int MAX = 2147483637;int MIN = -2147483639;//defaultdefault void doSth() {System.out.println("1.8新出的有方法体的默认方法");}//staticpublic static void test() {System.out.println("1.8新出的有方法体的静态方法");} } class Aaa implements IAAA{}
接口对常量访问方式:
接口名.静态常量
默认方法访问:
默认方法实现类的对象名.方法名()
静态方法访问:
接口名.方法名()访问接口中的静态方法
Aaa aa = new Aaa();// 不推荐System.out.println(aa.MAX);System.out.println(aa.MIN);// 推荐对静态常量访问方式:接口名.静态常量System.out.println(IAAA.MAX);System.out.println(IAAA.MIN);// 默认方法实现类的对象名.方法名()aa.doSth();//静态方法访问 // aa.test();//实现类的对象名.方法名()不能调用 // Aaa.test();IAAA.test();//接口名.方法名()访问接口中的静态方法