1.2 接口
1.2.1 接口的概念
接口是一种数据类型,引用数据类型。interface定义接口。
public interface 接口名{ }
1.1.1 接口的特性
[1] 接口中所有变量都是static final 类型,且都是默认都是public访问权限。
public interface MyInterface { int count = 10; public static final int count2 = 2; }
[2] 接口没有构造方法 => 接口不能实例化。
[3] 接口中所有的方法都是抽象方法(public abstract)。
public interface AInterface { // void showInfo(); // public abstract void showInfo(); // 推荐写法 // public void showInfo(); }
[4] A接口中定义的抽象方法可以被一个B类实现。
类B称为A接口的实现类(implement class)
ð 实现类必须实现接口中的抽象方法
public class ImplClass implements AInterface { @Override public void showAInfo() { } }
一个实现类可以实现多个接口。
public class ImplClass implements AInterface,BInterface{ @Override public void showAInfo() { System.out.println("实现A接口的方法"); } @Override public void showBInfo() { System.out.println("实现B接口的方法"); } }
一个类可以继承一个类,实现多个接口。继承在前,实现在后。
public class ImplClass extends AbstractClass implements AInterface,BInterface{ @Override public void showAInfo() { System.out.println("实现A接口的方法"); } @Override public void showBInfo() { System.out.println("实现B接口的方法"); } @Override public void test() { // TODO Auto-generated method stub } }
如果抽象父类定义的方法和接口定义的方法同名时,优先实现父类的同名抽象方法。实际开发规则此现象发生。
[5] 接口可以实现多继承,实现类如果实现了多继承的接口,需要把其他接口中的方法都实现。
public interface CInterface extends AInterface,BInterface{ public void test(); }
public class ImplClass implements CInterface{ @Override public void showAInfo() { // TODO Auto-generated method stub } @Override public void showBInfo() { // TODO Auto-generated method stub } @Override public void test() { // TODO Auto-generated method stub } }
总结:
接口定义了一些抽象方法。
ð 实现类实现接口中所有的抽象方法
ð 实现类具有了接口中定义的行为 => 实现类 has a 接口中定义的能力。
ð 接口拓展了实现类的能力
1.1 接口的应用
[1]接口可以实现多态
public class Test01 { public static void main(String[] args) { DriveInterface driveInterface = null; // 接口new实现类 driveInterface = new Student("二狗"); driveInterface.drive(); driveInterface = new Teacher("kallen"); driveInterface.drive(); } }
[2] 接口描述的是一种能力,提现在接口的方法上。
接口中定义的能力都是抽象方法。本身不提供任何实现。
ð 接口本身不关心方法如何实现,完全取决于实现类。
public class FaceDoor extends Door implements LockInterface{ @Override public void open() { System.out.println("自动开门..."); } @Override public void close() { System.out.println("自动关门"); } @Override public void lock() { System.out.println("刷脸上锁!"); } @Override public void unlock() { System.out.println("刷脸开锁!"); } }
思考:接口描述一种能力,有何用?
1.1 面向接口编程(A)
public class Test01 { public static void main(String[] args) { InkBoxInterface inkBoxInterface = null; inkBoxInterface = new ColorfulInkBox(); PaperInterface paperInterface = null; paperInterface = new A4Paper(); paperInterface = new B3Paper(); Writer writer = new Writer(paperInterface,inkBoxInterface); writer.print(); } }
接口也表示一种约定(规范),约定实现类应该具备什么能力。
接口更关心实现类具备什么能力,而不关心实现类如何实现。
面向接口编程
当完成一个系统性的工程时,需要多个模块之间进行配合实现。如果一个模块A需要模块B、C… 组合实现A模块的功能时,A模块需要预留出接口,约定支持模块应该具备的能力。
当B、C等模块不在满足系统需要时,在更换模块时,新模块只需要实现A模块预留的接口即可
抽象类和接口的比较
- 抽象类和接口都是引用数据类型,他们都不能创建对象。
- 他们都可以定义抽象方法,都可以实现多态。但是抽象可以定义非抽象方法,而接口中定义的都是抽象方法。
- 抽象类和接口都具有传递性。抽象类是单根性(单继承),而接口是多继承。
- 在概念上,都可以重写抽象方法。子类重写抽象类,实现类实现接口
- 抽象类和子类解决的是模块内的问题(代码重用,重写,多态)而接口解决的是模块间的问题 => 高内聚,低耦合。
1.1 Object
Object类是java的所有类的根类。
一个类如果没有继承任何类,默认继承Object
1.1.1 toString
返回对象的字符串表示形式。
public class Test01 { public static void main(String[] args) { Student student = new Student("二狗", 20); // 当直接输出对象时,默认调用toString方法 System.out.println(student); System.out.println(student.toString()); } }
如果要自定义对象的输出信息时,可以重写toString()方法。通过代码生成即可。
1.1.1 equals
一般用于比较两个对象是否内容相等。Object默认提供的是比较内存地址是否相等。如果要比较内容是否相等,一定要重写equals()方法。
两个对象的内容相等的标准:属性值都相等。
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (no == null) { if (other.no != null) return false; } else if (!no.equals(other.no)) return false; return true; }
1.1 内部类
类组织关系
[1] 平行关系。可以在一个文件中定义两个类。如果是一个文件定义两个类,一定有一个是主类(public 修饰)。主类一定和文件名保持一致。
public class Student { } class Teacher{ }
[2] 包含关系。可以在一个类中定义另外一个类。
public class Outer { class Inner{ } }
1.1.1 成员内部类
Inner类可以作为Outer类的成员而存在。Inner是Outer类的成员内部类,可以根据业务需要加访问修饰符。
public class Outer { class Inner{ public void showInfo() { System.out.println("我是Inner:showInfo"); } } }
[1] 创建成员内部类对象
package cn.sxt12.inner; import cn.sxt12.inner.Outer.Inner; public class Test01 { public static void main(String[] args) { // 【1】创建外部类对象 Outer outer = new Outer(); // 【2】创建内部类对象 Inner inner = outer.new Inner(); inner.showInfo(); } }
[2] 成员内部类可以直接访问外部类的私有属性(A)。
public class Outer { private String name = "Outer"; class Inner{ public void showInfo() { System.out.println("我是Inner:showInfo"); System.out.println(name); } } }
[3]如果内部类定义了和外部类同名的私有属性时(C)。
public class Outer { private String name = "Outer"; class Inner{ private String name = "Inner"; public void showInfo() { System.out.println("我是Inner:showInfo"); System.out.println(name); System.out.println(this.name); // 访问外部类的私有属性 System.out.println(Outer.this.name); } } }
1.1.1 静态内部类
如果一个内部类被static修饰,就变成了静态内部类。
public class Outer { static class Inner{ public void showInfo() { System.out.println("我是Inner:static showInfo"); } } }
[1] 创建静态内部类对象
package cn.sxt12.staticinner; import cn.sxt12.staticinner.Outer.Inner; public class Test01 { public static void main(String[] args) { Inner inner = new Outer.Inner(); inner.showInfo(); } }
[2] 静态内部类中可以直接访问外部类的(私有)静态成员。(A)
public class Outer { static String name = "outer"; static class Inner{ public void showInfo() { System.out.println("我是Inner:static showInfo"); System.out.println(name); } } }
[3] 静态内部类定义了和外部类同名的静态属性时(C)
public class Outer { static String name = "outer"; static class Inner{ static String name = "inner"; public void showInfo() { System.out.println("我是Inner:static showInfo"); // 默认访问内部类 System.out.println(name); System.out.println(Inner.name); System.out.println(Outer.name); } } }
1.1.1 方法内部类
如果一个类定义方法中,这个类称为方法内部类。
public class Outer { public void test() { class Inner{ public void showInfo() { System.out.println("method:inner class"); } } } }
[1] 创建方法内部类对象
public class Outer { public void test() { class Inner{ public void showInfo() { System.out.println("method:inner class"); } } // Inner inner = new Inner(); // inner.showInfo(); // 匿名对象(只使用一次的对象) new Inner().showInfo(); } }
[2]方法内部类中的方法可以直接访问方法的局部变量。
public class Outer { public void test() { // 方法的局部变量 int a = 10; class Inner{ public void showInfo() { System.out.println("method:inner class"); System.out.println("a="+a); // a = 100;(error) } } new Inner().showInfo(); } }
总结:
在方法中的局部变量进入方法内部类时被加了final修饰。在方法内部类中只能读取方法的局部变量,不能修改。
思考:在方法内部类中定义同名的局部变量时,该如何访问?(C)
1.1.1 匿名内部类(A)
当一个类只使用一次时,可以把这个类声明为匿名类。
匿名类一般在方法中使用,形成方法匿名内部类,简称匿名内部类。
匿名内部类一般只使用一次。
匿名内部类在形式上一定会出现:实现接口(implement)
public class Outer { public void test() { /* class Inner implements MyInterface{ @Override public void showInfo() { System.out.println("showinfo"); } } new Inner().showInfo(); */ // 匿名内部类 new MyInterface(){ @Override public void showInfo() { System.out.println("showinfo"); } }.showInfo(); } }