接口
概念:接口相当于特殊的抽象类,定义方式、组成部分与抽象类类似。使用interface关键字定义接口。
特点:
- 没有构造方法,不能创建对象。
- 只能定义:公开静态常量、公开抽象方法。
public interface MyInterface {
//接口中:只能定义公开的静态常量和公开抽象方法
// 没有构造方法、动态、静态代码块
public static final int a = 10;
public abstract void show();
}
和抽象类区别
相同点:
- 可编译成字节码文件。
- 不能创建对象。
- 可以作为引用类型。
- 具备Object类中所定义的方法。
不同点: - 所有属性都是公开静态常量,隐式使用public static final修饰。
- 所有方法都是公开抽象方法,隐式使用public abstract修饰。
- 没有构造方法、动态代码块、静态代码块。
示例
public interface A {
void aa();
}
public interface B {
void bb();
}
public interface C extends A,B{
void cc();
}
public class D implements C{
@Override
public void aa() {
System.out.println("aa");
}
@Override
public void bb() {
System.out.println("bb");
}
@Override
public void cc() {
System.out.println("cc");
}
}
public class Test {
public static void main(String[] args) {
/**
* 接口中:
* 抽象方法和常量
* 抽象方法省略了public abstract
* 常量省略了 public static final
* 实现接口中方法必须是public修饰
* 没有构造方法,动态代码块和静态代码块
* 和抽象类一样不能创建对象
*
*
* 类和类 单继承 extends 父类名称
* 类和接口 多重实现 implements 接口名称1 , 接口名称2 , 接口名称n
* 接口和接口 多重继承 extends 父接口1 , 父接口2 , 父接口n
*
* 也可以继承父类,然后实现接口
* extends 父类 implements 接口1,接口2,接口n
*/
A d1=new D();
d1.aa();
B d2=new D();
d2.bb();
C d3=new D();
d3.cc();
d3.aa();
d3.bb();
D d4=new D();
d4.aa();
d4.bb();
d4.cc();
}
}
接口回调
1.创建接口
2.使用接口
3.实现接口
先有接口的调用再有接口的实现
利用Comparator接口进行回调函数排序
示例
//Student类
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//Comparator 接口实现
public class MyComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
// return o2.getAge()-o1.getAge();
//比较字符串,比较特殊
return o1.getName().compareTo(o2.getName());
}
}
//测试类
public class Test {
public static void main(String[] args) {
Student stu1=new Student("zs",20);
Student stu2=new Student("ls",25);
Student stu3=new Student("ww",18);
Student stu4=new Student("zl",50);
Student[] students=new Student[4];
students[0]=stu1;
students[1]=stu2;
students[2]=stu3;
students[3]=stu4;
Arrays.sort(students, new MyComparator());
for (int i = 0; i < students.length; i++) {
System.out.println(students[i].getAge()+"--"+students[i].getName());
}
}
}
内部类
内部类的概念:
在一个类中定义的类,称之为内部类(InnerClass),外面的类的称之为外部类(OutClass)
内部类的分类:
- 1、成员内部类
- 2、静态内部类
- 3、局部内部类
- 4、匿名内部类
内部类的特点:
内部类可以访问到外部类的私有成员,且不破坏封装性
内部类也会生成.class文件。名为:外部类名$内部类名.class - 一个java 文件中可以编写多个类,但是只能有一个类能使用public修饰,称之为主类。主类名必须与文件名一致
- 建议:以后开发中,一个java文件就编写一个类
public class OutClass {//外部类
//内部类
public class InnerClass{
}
}
成员内部类
- 1、成员内部类中只能定义非静态属性和方法
- 2、成员内部类中可以访问外部类的成员,私有的可以,静态的也可以
成员内部类如何创建对象
语法: 内部类 对象名 = new 外部类().new 内部类();
public class OuterClass1 {
String name;
private String hobby;
static int age;
public void show() {
System.out.println("show()");
}
public class InnerClass{
//定义属性
int a ;
//static int b; //错误 ,成员内部类中不能定义静态变量
//定义方法
public void m1() {
System.out.println("成员内部类的成员变量"+a);
System.out.println("外部类的成员变量"+name);
System.out.println("外部类的私有成员变量"+hobby);
System.out.println("外部类的静态变量"+age);
}
// public static void m2() {//错误 成员内部类中不能定义静态方法
// }
}
}
静态内部类
- 1、静态内部类中可以定义属性和方法,也能定义静态属性和方法
- 2、静态内部类中只能访问静态外部类的静态属性和方法
静态内部类创建对象
语法:内部类 对象名 = new 外部类.内部类();
public class OuterClass2 {
String name;
static int age;
private static String hobby;
public static class InnerClass2{
//定义属性
int a;
static int b;
//定义方法
public void m1() {
//System.out.println("外部类的成员变量"+name);
System.out.println("外部类的静态变量"+age);
System.out.println("外部类的私有静态变量"+hobby);
}
public static void m2() {
}
}
}
局部内部类
局部内部类: 定义在方法中
- 1、成员内部类中只能定义非静态属性和方法
- 2、成员内部类中可以访问外部类的成员,私有的可以,静态的也可以
- 3、局部内部类只能在方法内创建对象
面试题: - 局部内部类只能访问局部常量。
- 在jdk1.7版本中,如果局部变量在局部内部类中使用必须要显式的加上final
- 在jdk1.8版本中,final是默认加上的
- 因为局部变量在方法结束后,就会被销毁,而局部内部类的对象却要等到内存回收机制进行销毁所以如果是常量的话,那么常量就会被存放在常量池中,
public class OuterClass4 {
String name;
private int age;
static String hobby;
public void show() {
int num = 10;
class InnerClass4{
public void m1() {
System.out.println("外部类的成员变量"+name);
System.out.println("外部类私有的成员变量"+age);
System.out.println("外部类静态变量"+hobby);
//num = 20;
System.out.println("访问局部变量"+num);
}
//static int b;
//public static void m2() {}
}
InnerClass4 in = new InnerClass4();
in.m1();
}
}
匿名内部类(重点)
匿名内部类:本身就是一个对象
语法:
new 父类(){
重写父类的方法
}
特点:
- 1、匿名内部类本身就是一个对象
- 2、一般在匿名内部类中不会定义属性和方法,因为没有意义
- 3、匿名内部类的父类一般都是抽象类或者是接口
匿名内部类的应用场景 - 如果一个方法的参数是接口,且这个接口只需要实现一次,那么就可以使用匿名内部类
- 这个接口的实现每一次都不相同,就可以使用匿名内部类
Father f = new Father() {
int a;
public void m1() {
System.out.println("m1()...");
}
};
匿名内部类的应用场景
public class Test {
public static void main(String[] args) {
//使用匿名内部类作为参数传递
gdbh(14,new MyInterface() {
@Override
public boolean isZS(int num) {
for (int i = 2; i < num; i++) {
if(num % i == 0) {
return false;
}
}
return true;
}
});
}
public static void gdbh(int num,MyInterface mi) {
for (int i = 3; i <= num/2; i++) {
if(mi.isZS(i) && mi.isZS(num-i)) {
System.out.println(num+"="+i+"+"+(num-i));
}
}
}
}
interface MyInterface{
boolean isZS(int num);
}
内部类中this用法
this表示当前类对象
- 如果有内部类,那么this在哪个类中使用就是指的哪个类的当前类的对象
- 如果要想调用外部类的属性和方法,那么需要使用外部类名.this.属性或者方法名
public class OuterClass3 {
String name = "张三";
public class InnerClas3{
String name ="李四";
public void m1() {
String name = "王五";
System.out.println("方法中的name"+name);
System.out.println("内部类中的name"+this.name);
//this关键字表示的时候当前类的对象,如果在内部类中this表示的是内部类的对象,
//如果想要表示外部类的对象,外部类名.this
System.out.println("外部类中的name"+OuterClass8.this.name);
}
}
}