接口,使用interface修饰,是个特殊的抽象类,当抽象类里只有静态常量或抽象方法时,可以用接口代替
注意:
- 接口里可以有静态常量或抽象方法,JDK1.8新特性还添加了默认方法和静态方法
- 接口可以继承多个接口
- 一个类只能继承一个父类,可以实现多个接口
- 接口不能new对象
public class Test {
public static void main(String[] args) {
MyClass m = new MyClass();
m.defaultMethod();//调用I1接口中的默认方法
I1.staticMethod();//调用I1接口中的静态方法
}
}
interface I1{
public abstract void i1Method();
default void defaultMethod(){
System.out.println("I1中的默认方法");
}
public static void staticMethod(){
System.out.println("I1中的静态方法");
}
}
interface I2 extends I3,I4{
public abstract void i2Method();
}
interface I3{
public abstract void i3Method();
}
interface I4{
public abstract void i4Method();
}
class MyClass implements I1,I2{
@Override
public void i3Method() {
System.out.println("实现I3中的抽闲抽象方法");
}
@Override
public void i4Method() {
System.out.println("实现I4中的抽闲抽象方法");
}
@Override
public void i2Method() {
System.out.println("实现I2中的抽闲抽象方法");
}
@Override
public void i1Method() {
System.out.println("实现I1中的抽闲抽象方法");
}
}
interface IPerson{
public abstract void eat();
}
class Chinese implements IPerson{
@Override
public void eat() {
System.out.println("中国人吃山珍海味");
}
}
class Japanese implements IPerson{
@Override
public void eat() {
System.out.println("日本人吃马赛克");
}
}
关系 | 描述 |
---|---|
类与类 | 单继承 |
类与接口 | 多实现 |
接口与接口 | 多继承 |
多种形态
public class Test {
public static void main(String[] args) {
/**
* 需求:老师骑着自行车、汽车上班
*
* 注意:此代码的设计符合OCP(开闭)原则
*
* OCP原则 - OpenClosePrinciple
* 含义:需求升级时,对创建新类是欢迎的,对修改原有类是拒绝的
* 好处:修改原有类容易造成bug
*
* 体现:试一试新加一个飞机类
* 步骤:
* 创建Plane类,继承Vehicle类,
* 修改main方法中Vehicle v = new Plane();
* 注意:修改main方法不算修改,因为是测试代码的
*/
Teacher t = new Teacher();
//类的多态:子类对象指向父类引用,引用里存的是子类对象的地址
//Vehicle v = new Bike();
Vehicle v = new Car();
t.open(v);
System.out.println("老师欣赏沿途的风景...");
t.close(v);
}
}
class Teacher{
public void open(Vehicle v){
//启动
v.start();
}
public void close(Vehicle v){
//关闭
v.stop();
}
}
class Car extends Vehicle{
@Override
public void start() {
System.out.println("汽车开");
}
@Override
public void stop() {
System.out.println("汽车停");
}
}
class Bike extends Vehicle{
@Override
public void start() {
System.out.println("自行车开");
}
@Override
public void stop() {
System.out.println("自行车停");
}
}
abstract class Vehicle{
//交通工具
public void start();
public void stop();
}
public class Test {
public static void main(String[] args) {
/**
* 需求:电脑连接usb,使用鼠标和硬盘
*
* 注意:此代码的设计符合OCP(开闭)原则
*
* 体现:试一试新加一个键盘Keyboard类
* 步骤:
* 创建Keyboard类,实现IUSB接口,
* 修改main方法中IUSB usb = new Keyboard();
* 注意:修改main方法不算修改,因为是测试代码的
*/
Computer com = new Computer();
//接口的多态:实现类对象执行接口的引用,引用里存的是实现类对象的地址
//IUSB usb = new Mouse();
IUSB usb = new Disk();
com.connection(usb);
}
}
class Computer{
//电脑类
public void connection(IUSB usb){
usb.use();
}
}
class Mouse implements IUSB{
@Override
public void use() {
System.out.println("鼠标:左点点、右点点");
}
}
class Disk implements IUSB{
@Override
public void use() {
System.out.println("硬盘:上传文件、下载文件");
}
}
interface IUSB{
//接口
public void use();//使用的抽象方法
}
引用数据的转型
向上转型:子类 转 父类类型
向下转型:父类 转 子类类型,又称为引用数据类型的强转
向上转型就是多态
注意:
- 可以直接调用父类非私有化属性
- 可以直接调用父类非私有化方法
3. 可以直接调用子类重写父类的方法
向上转型即多态的缺点:不能调用子类的属性和方法
public class Test {
public static void main(String[] args) {
//向上转型:就是多态
Father f = new Son();
System.out.println(f.fatherStr);//父类属性
f.fatherMethod01();//父类方法01
f.fatherMethod02();//子类重写父类方法02
}
}
class Father{
String fatherStr = "父类属性";
public void fatherMethod01(){
System.out.println("父类方法01");
}
public void fatherMethod02(){
System.out.println("父类方法02");
}
}
class Son extends Father{
String fatherStr = "子类和父类同名的属性";
String sonStr = "子类属性";
public void sonMethod(){
System.out.println("子类方法");
}
@Override
public void fatherMethod02() {
System.out.println("子类重写父类方法02");
}
}
向下转型一定要用instanceof判断对象类型
public class Test {
public static void main(String[] args) {
Animal an = new Dog();//向上转型
//Cat cat = (Cat) an;//直接向下转型容易造成类型转换异常
if(an instanceof Dog){
//判断引用an中指向的对象是否是Dog类
//向下转型
Dog dog = (Dog) an;
}else if(an instanceof Cat){
//判断引用an中指向的对象是否是Cat类
//向下转型
Cat cat = (Cat) an;
}
}
}
class Animal{
//动物类
}
class Dog extends Animal{
}
class Cat extends Animal{
}
一个类里声明另外一个类
public class Test01 {
public static void main(String[] args) {
//成员内部类
//创建出成员内部类的对象
Inner inner = new Outter().new Inner();
inner.print();
}
}
public class Outter {
private String str1 = "aaa";
String str2 = "222";
protected String str3 = "333";
public String str4 = "444";
static String str5 = "555";
final String str6 = "666";
//成员内部类
public class Inner{
private String str1 = "bbb";
public void print(){
System.out.println("成员内部类里的方法");
System.out.println(Outter.this.str1);//调用外部类的str1属性
System.out.println(str1);//this.str1
System.out.println(str2);
System.out.println(str3);
System.out.println(str4);
System.out.println(str5);//Outter.str5
System.out.println(str6);
}
}
}
public class Test01 {
public static void main(String[] args) {
//静态内部类
//创建静态内部类的对象
Inner inner = new Outter.Inner();
inner.print();
}
}
public class Outter {
private String str1 = "aaa";
String str2 = "222";
protected String str3 = "333";
public String str4 = "444";
static String str5 = "555";
final String str6 = "666";
//静态内部类
public static class Inner{
/**
* 为什么静态内部类里不能调用外部类的成员变量:
* 因为创建静态内部类对象时不用创建外部类对象,成员变量不存在,所以在静态内部类里调用不到
* 为什么静态内部类里可以调用外部类的静态变量:
* 创建静态内部类对象时,先把外部类的字节码文件加载到方法区,这时外部类的静态变量就加载到静态区,所以静态内部类可以调用的到
*/
public void print(){
System.out.println("静态内部类的方法");
System.out.println(str5);//Outter.str5
}
}
}
public class Test01 {
public static void main(String[] args) {
//接口内部类
//创建接口内部类的对象
Inner inner = new IOutter.Inner();
inner.print();
}
}
//接口
public interface IOutter {
//接口内部类(默认使用static修饰)
public class Inner{
public void print(){
System.out.println("接口内部类的方法");
}
}
}
public class Test01 {
public static void main(String[] args) {
/**
* 局部内部类
*/
Outter outter = new Outter();
outter.method();
}
}
public class Outter {
public void method(){
//局部内部类
class Inner{
public void print(){
System.out.println("局部内部类的方法");
}
}
//创建局部内部类的对象
Inner inner = new Inner();
inner.print();
}
}
public class Test01 {
public static void main(String[] args) {
/**
* 局部内部类
*/
Outter outter = new Outter();
Object obj = outter.method();
System.out.println(obj);
}
}
public class Outter {
public Object method(){
//当局部内部类中使用到了外部类的变量时,此变量默认添加final
//为什么
//因为使用fianl修饰的变量存储在常量池中,声明周期更长
String str = "abc";
//局部内部类
class Inner{
@Override
public String toString() {
return str;
}
}
return new Inner();
}
}
public class Test01 {
public static void main(String[] args) {
/**
* 匿名内部类
*/
//1.创建匿名类,继承A类
//2.重写method方法
//3.new 匿名类的对象
//4.把匿名类的对象地址赋值给父类的引用 -- 多态
A a = new A() {
@Override
public void method() {
System.out.println("xxxx");
}
};
//1.创建匿名类,实现I1接口
//2.重写method方法
//3.new 匿名类的对象
//4.把匿名类的对象地址赋值给接口的引用 -- 多态
I1 i1 = new I1() {
@Override
public void method() {
System.out.println("xxxx");
}
};
/**
* 什么时候使用匿名内部类:
* 该抽象的子类 或 接口的实现类 只用到一次时,就可以考虑使用匿名内部类
*/
}
}
abstract class A{
public abstract void method();
}
interface I1{
public abstract void method();
}