接口变化 JDK 1.8 之后,接口的语法有了新的变化。增加了两类成员。
静态方法 public static。static 不可以省略,通过 “接口名.方法名” 来进行调用。
默认方法 public default。default 不可以省略,通过 “实现类对象.方法名” 来进行调用。
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 package com.atguigu.code;public class NewInterface { public static void main (String[] args) { MyInter.print(); MyImpl myImpl = new MyImpl(); myImpl.test(); myImpl.method(); } } interface MyInter { String INFO = "info" ; void test () ; public static void print () { System.out.println("1.8 接口新增静态方法" ); } public default void method () { System.out.println("1.8 接口新增默认方法" ); } } class MyImpl implements MyInter { @Override public void test () { System.out.println("实现接口的抽象方法" ); } }
接口中默认方法冲突
在实现多个接口时候,接口中都有签名相同的方法。
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 package com.atguigu.code;public class InterfaceSameMethod { public static void main (String[] args) { C c = new C(); c.method(); } } interface A { public default void method () { System.out.println("A 默认方法" ); } } interface B { public default void method () { System.out.println("B 默认方法" ); } } class C implements A , B { @Override public void method () { A.super .method(); B.super .method(); } }
在继承和接口的实现中,父类和接口中都有签名相同的方法。
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 42 43 44 package com.atguigu.code;import org.omg.CORBA.PUBLIC_MEMBER;public class InterfaceSameMethod { public static void main (String[] args) { D d = new D(); d.method(); E e = new E(); e.method(); F f = new F(); f.method(); } } interface A { public default void method () { System.out.println("A 默认方法" ); } } class C { public void method () { System.out.println("C 中的 method" ); } } class D extends C implements A { } class E extends C implements A { public void method () { A.super .method(); } } class F extends C implements A { public void method () { System.out.println("自己实现" ); } }
内部类 含义 :当一个类的内部,仍然有一个完整的结构。这个完整的结构仍然需要一个类进行描述,因为有自己的特征(属性,方法),并且这个内部类是为外部类服务的。
分类 :
成员内部类:和成员变量一样,在类中,方法外。成员内部类又可以分为两种,分别是静态成员内部类(简称静态内部类 )和非静态成员内部类(简称成员内部类 )
局部内部类:在类中,方法内。局部内部类又可以分为两种,分别是由名字的局部内部类(简称为局部内部类 )和没有名字的局部内部类(简称为匿名内部类 )
常见程度:静态内部类 = 成员内部类 > 匿名内部类 > 局部内部类
静态内部类 静态内部类中,类的5大成员它都可以拥有。
属性:静态和非静态属性
方法:静态方法和非静态方法。在抽象的静态内部类中,还可以有抽象方法
代码块:静态的和非静态的
构造器:有参的和无参的
内部类:语法上可以,但是太复杂了,一般不这么写
静态内部类的修饰符 :
权限修饰符:4个都可以有
static必须有
abstract 可以有
final 可以有
使用 :
在静态内部类中不允许使用外部类的非静态的成员(static 中不能使用非 static)
在外部类中,使用静态内部类和使用其他类一样
在外部类的外面使用静态内部类,不需要外部内的对象。例如下面的 Outer.Inner
在外部类的外面要调用静态内部类的非静态方法时,则需要静态内部类的对象。例如:
Outer.Inner obj = new Outer.Inner(); obj.test();
在外部类的外面要调用静态内部类的静态方法时,则不需要静态内部类的对象。例如:Outer.Inner.test2();
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 42 43 44 45 46 47 48 49 50 package com.atguigu.code;import com.atguigu.code.Outer.Inner;public class TestStaticInner { public static void main (String[] args) { Outer.Inner obj = new Outer.Inner(); obj.test(); Outer.Inner.test2(); } } class Outer { private static int i; private int j; static class Inner { public void test () { System.out.println(i); } public static void test2 () { System.out.println(i); } } public Inner GetInner () { Inner inner = new Inner(); return inner; } }
静态内部类也有自己的字节码文件,文件格式为 外部类$静态内部类.class
非静态内部类 非静态内部类中,类的5大成员它都可以拥有。但是都是非静态的
属性:非静态属性
方法:非静态方法。在抽象的静态内部类中,还可以有抽象方法
代码块:非静态的
构造器:有参的和无参的
内部类:语法上可以,但是太复杂了,一般不这么写
非静态内部类的修饰符 :
权限修饰符:4个都可以有
static 没有
abstract 可以有
final 可以有
使用 :
在非静态内部类中可以使用外部类的所有成员
在外部类中,使用非静态内部类有限制。在外部类的静态方法中不允许使用非静态内部类。(static 中不能使用非 static)
在外部类外面要调用非静态内部类的非静态方法,需要外部类的对象和内部类的对象。例如:
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 42 43 44 package com.atguigu.code;public class TestStaticInner2 { public static void main (String[] args) { Outer2 outer2 = new Outer2(); Outer2.Inner inner = outer2.new Inner(); inner.test(); Outer2.Inner inner2 = outer2.getInner(); inner2.test(); } } class Outer2 { private static int i; private int j; class Inner { public void test () { System.out.println(i); System.out.println(j); } } public Inner getInner () { return new Inner(); } }
非静态内部类也有自己的字节码文件,文件格式为 外部类$非静态内部类.class
局部内部类 局部内部类的修饰符 :
权限修饰符:没有
static 没有
abstract 可以有
final 可以有
使用 :
局部内部类的作用域只在类所在的方法中,非常狭窄,这也是局部内部类用得比较少的原因。
局部内部类中是否能使用外部类的非静态成员变量,要看所在方法是否是静态的。(要遵循 static 中不能使用非 static 的原则)
局部内部类中可以使用所在方法的局部变量,但是该局部变量必须加 final 声明 (JDK 1.8 之前必须手动加上 final,1.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 25 26 27 28 29 30 31 32 33 34 35 36 37 package com.atguigu.code2;public class TestLocalInner { } class Outer { public static int i = 10 ; public int j = 10 ; public void outTest () { int a = 10 ; class Inner { public void test () { System.out.println(i); System.out.println(j); System.out.println(a); } } Inner inner = new Inner(); inner.test(); } public static void outMethod () { class Inner { public void test () { System.out.println(i); } } } }
局部内部类也有自己的字节码文件,文件格式为 外部类$数字+局部内部类.class。有数字的原因是很可能有多个名称相同的局部内部内,例如上面例子中就有两个局部内部类 Inner
匿名内部类 匿名内部类的声明位置在创建对象的位置,特点是一边声明一边创建对象,且匿名内部类只有唯一的一个对象。匿名内部类没有任何修饰符,也没有名字。匿名内部类有构造器(默认的构造器),但是不能复写(因为没有名字)
使用 :匿名内部类是一种特殊的局部内部类,所以凡事局部内部类的限制,匿名内部类都有。如下所示
局部内部类的作用域只在类所在的方法中,非常狭窄,这也是局部内部类用得比较少的原因。
局部内部类中是否能使用外部类的非静态成员变量,要看所在方法是否是静态的。(要遵循 static 中不能使用非 static 的原则)
局部内部类中可以使用所在方法的局部变量,但是该局部变量必须加 final 声明 (JDK 1.8 之前必须手动加上 final,1.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 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 package com.atguigu.code3;public class TestNoNameInner { public static void main (String[] args) { MyClass myClass = new MyClass() { @Override public void test () { System.out.println("匿名内部类重写 MyClass test 方法" ); } }; myClass.test(); MyClass myClass2 = new MyClass("父类有参构造" ) { @Override public void test () { System.out.println("匿名内部类重写 MyClass test 方法" ); } }; myClass2.test(); MyInner myInner = new MyInner() { @Override public void test () { System.out.println("重写接口的抽象方法 test" ); } }; myInner.test(); } } abstract class MyClass { private String info; public abstract void test () ; public MyClass (String info) { super (); this .info = info; } public MyClass () { super (); } public String getInfo () { return info; } public void setInfo (String info) { this .info = info; } } interface MyInner { void test () ; }
匿名内部类也有自己的字节码文件,文件格式为 外部类$数字.class。因为没有名字,所以就是数字表示
Comparator 之前学习了 java.lang 包下的 Comparator。现在 java.utils 下还有一个 Comparator 接口。里面有一个 compare 方法,接收两个对象,如果第一个对象大于第二个,返回一个正整数,相等返回0,否则返回负整数。那么为什么会多有一个 Comparator 接口呢,因为如果要对一个对象的多个特性进行比较排序的化,java.utils.Comparator 结合 Arrays.sort 使用更加方便。
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 package com.atguigu.code3;import java.util.Arrays;import java.util.Comparator;public class TestComprator { public static void main (String[] args) { Student[] arr = new Student[3 ]; arr[0 ] = new Student(1 , "张三" , 88 ); arr[1 ] = new Student(3 , "李四" , 99 ); arr[2 ] = new Student(2 , "王五" , 77 ); Arrays.sort(arr); for (int i = 0 ; i < arr.length; i++) { System.out.println(arr[i]); } System.out.println("-------------------------" ); Arrays.sort(arr, new Comparator() { @Override public int compare (Object o1, Object o2) { Student student1 = (Student) o1; Student student2 = (Student) o2; return student1.getScore() - student2.getScore(); } }); for (int i = 0 ; i < arr.length; i++) { System.out.println(arr[i]); } } } class Student implements Comparable { private int id; private String name; private int score; @Override public String toString () { return "Student [id=" + id + ", name=" + name + ", score=" + score + "]" ; } public Student (int id, String name, int score) { super (); this .id = id; this .name = name; this .score = score; } public Student () { super (); } public int getId () { return id; } public void setId (int id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public int getScore () { return score; } public void setScore (int score) { this .score = score; } @Override public int compareTo (Object o) { Student student = (Student) o; return this .id - student.id; } }