08--Java 面向对象(三) 关键字、补充类

系列文章专栏

JavaSE自学全路线



前言

该篇笔记主要记录了 Java 面向对象编程中一些关键字的使用,包括 this、package、import、super、static、final、abstract,并补充了两个常用类,即 Object 类和包装类,最后介绍了接口的相关知识和应用。


一、this 关键字

1.1 this 调用属性、方法、构造器

  • this 的作用:来修饰、调用属性、方法、构造器
  • this 修饰属性和方法:this 为当前对象,或当前正在创建的对象
  • 在类的方法中 this 的调用说明
    • 调用方式:在方法中,采用this.属性或者是this.方法调用当前对象属性和方法;
    • 一般情况下:省略this.
    • 特殊情况下(方法的形参和类的属性同名):显式的使用this.变量的方式,表明此变量是属性,而非形参
  • 在类的构造器中 this 的调用说明
    • 调用方式:在方法中,采用this.属性或者是this.方法调用正在创建的对象属性和方法;
    • 一般情况下:省略this.
    • 特殊情况下(方法的形参和类的属性同名):显式的使用this.变量的方式,表明此变量是属性,而非形参
  • this 调用构造器的补充说明
    • 在类的构造器中,可显式使用this(形参列表)的方式,调用本类中重载的其他构造器,但不能通过this(形参列表)的方式调用自己;
    • 如果一个类中声明了n个构造器,则最多有n -1个构造器中使用this(形参列表)
    • this(形参列表)必须声明在类的构造器的首行;
    • 在类的一个构造器中,最多只能声明一个this(形参列表)

1.2 this 练习

public class PersonTest {
    public static void main(String []args) {
        Person p1 = new Person();   //Person()就相当于一个构造器
  	p1.eat;
  	Person p2 = new Person("Tom",20)
  	System.out.println(p2.getName());
    }
}
class Person{
 	private String name;
 	private int age;
 	// 构造器
 	public Person(){
 	}
 	public Person(String name){
  		this();   // 调用构造器
  		this.name = name;
 	}
 	public Person(String name,int age){
  		this(name);   // this(name)实现了this.name = name的功能
  		//this.name = name;
  		this.age = age;
 	} 
 	// 方法
 	public void setName(String name){   //形参和属性同名,采用this调用当前对象
  		this.name = name;
 	}
 	public String getName(){
  		return this.name;
 	}
 	public void eat(){
  		System.out.println("人可以吃饭");
  		this.study();
 	}
 	public void study(){
  		System.out.println("人可以学习");
 	}
}

二、package 和 import 关键字

2.1 package 关键字

  • package 的使用
    • 作用:更好的实现项目中类的管理,使用 package 声明类或接口所属的包,声明在源文件的首行
    • 说明:属于标识符,遵循标识符的命名规则、规范(包名–小写);每“.”一次,就代表一层文件目录
    • 补充:同一个包下,不能命名同名接口或同名类;不同包下,可以命名同名的接口或类
  • JDK 中主要的包介绍
    • java.lang:包含一些 Java 语言的核心类,如 String、Math、Integer、System 和 Thread,提供常用功能
    • java.net:包含执行与网络相关的操作的类和接口
    • java.io:包含能提供多种输入/输出功能的类
    • java.util:包含一些实用工具类,如定义系统特性、接口的集合框架类、使用与日期日历相关的函数
    • java.text:包含了一些 java 格式化相关的类
    • java.sql:包含了 java 进行 JDBC 数据库编程的相关类/接口
    • java.awt:包含了构成抽象窗口工具集(abstractwindowtoolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)

2.2 import 关键字

  • import 的使用 ---- 导入
    • 在源文件中显式的使用 import 结构导入指定包下的类、接口
    • 声明在包的声明和类的声明之间,如果需要导入多个结构,则并列写出即可
    • 使用xxx.*的方式,表示可以导入xxx包下的所有结构
    • 如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此 import 语句
    • 使用不同包下的同名的类,需要使用类的全类名的方式指明调用的是哪个类
    • 如果已经导入java.a包下的类,若需要使用a包的子包下的类,仍然需要导入
    • import static 组合的使用:调用指定类或接口下的静态的属性或方法

三、super 关键字

3.1 super 调用属性、方法、构造器

  • super 含义:理解为父类的
  • super 使用
    • 调用方式:在子类的方法或构造器中,采用super.属性或者是super.方法调用父类中声明的属性或方法
    • 一般情况下:省略super.
    • 特殊情况1(子类和父类中定义了同名的属性):显式的使用super.属性的方式,表明调用的是父类中声明的属性
    • 特殊情况2(子类重写了父类中的方法):显式的使用super.方法的方式,表明调用的是父类中被重写的方法
  • super 调用构造器的补充说明
    • 在子类的构造器中显式的使用super(形参列表)的方式,调用父类中声明的指定的构造器
    • super(形参列表)必须声明在子类的构造器的首行;
    • 在类的构造器中,针对于this(形参列表)super(形参列表)只能二选一,不能同时出现
    • 在构造器的首行,既没有显式的声明this(形参列表)super(形参列表),则默认的调用的是父类中的空参构造器super()
    • 在类的多个构造器中,至少有一个类的构造器使用了super(形参列表)调用父类中的构造器

3.2 super 练习

// 父类:Person类
public class Person{
 	String name;
 	int age;
 	int id = 1001;  
 
 	public Person(){
 	}
 	public Person(String name,int age){
  		this.name = name;
  		this.age = age;
 	}
 
 	public void eat(){
  		System.out.println("人,吃饭")
 	}
 	public void walk(){
  		System.out.println("人,走路")
 	} 
}
// 子类:Student类
public class Student extends Person{
 	String major;
 	int id = 1002;   //定义了和父类同名的属性
 
 	public Student(){
 	}
 	public Student(String name,int age,String major){
  		//this.name = name;
  		//this.age = age;
  		super(name,age);  //调用父类中声明的指定的构造器
  		this.major = major;
 	}
 	public void eat(){
  		System.out.println("学生,吃有营养的东西");
 	}
 	public void study(){
  		System.out.println("学生,学习");
  		this.eat(); //子类方法重写,调用的是子类中重写的方法,可以省略
  		super.eat();  //调用的是父类中被重写的方法
  		super.walk();//未重写的,用"this."或"super."调用都可以
 	} 
 	public void show(){
  		System.out.pringln(this.id);
  		System.out.pringln(super.id); //父类中声明的属性
 	}
}
// 测试类
public class ExtendsTest {
    public static void main(String []args) {
        Student s1 = new Student();
  	s1.eat();
  	s1.study();
  	s1.show();
    }
}

四、Object 类的使用

4.1 Object 类的说明

  • java.lang.Object 类
    • Object 类是所有 Java 类的根父类
    • 如果在类的声明中未使用 extends 关键字指明其父类,则默认父类为 java.lang.Object 类
    • Object 类中的功能(属性、方法)就具有通用性
      • 属性:无
      • 方法:equals()、toString()、 getClass()、hashCode()、clone()、finalize()、wait()、notify()、notifyAll() 等
      • 构造器:Object 类只声明了一个空参的构造器

4.2 Object 类中主要结构

方法名称类型描述
public Object()构造构造器
public boolean equals(Object obj)普通对象比较
public int hashCode()普通取得Hash码
public String toString()普通对象打印时调用

4.2.1 equals() 方法的使用

  • == 运算符的使用
    • 可以使用在基本数据类型变量和引用数据类型变量中
      • 比较基本数据类型变量:比较两个变量保存的数据是否相等 (不一定类型要相同)
      • 比较引用数据类型变量:比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
    • == 符号使用时,必须保证符号左右两边的变量类型一致
  • equals() 方法的使用:是一个方法,而非运算符,只能适用于引用数据类型
  • Object 类中的 equals()
    • 定义:`public boolean equals(Object obj){return (this == obj);}
    • Object 类中定义的 equals() 和== 的作用是相同的,比较两个对象的地址值是否相同,即两个引用是否指向同一个对象实体
    • 像 String、Date、File、包装类等都重写了 Object 类中的 equals() 方法,重写后不再比较两个引用的地址是否相同,而是比较两个对象的实体内容是否相同
    • 通常情况下,自定义的类如果使用 equals(),也通常是比较两个对象实体内容是否相同,那么,就需要对 Object 类中的 equals() 进行重写
  • 重写 equals() 方法的原则
    • 对称性:如果 x.equals(y) 返回是“true”,那么 y.equals(x) 也应该返回是“true”
    • 自反性:x.equals(x) 必须返回是“true”
    • 传递性:如果 x.equals(y) 返回是“true”,而且 y.equals(z) 返回是“true”,那么 z.equals(x) 也应该返回是“true”
    • 一致性:如果 x.equals(y) 返回是“true”,只要x和y内容一直不变,不管你重复 x.equals(y) 多少次,返回都是“true”
    • 任何情况下,x.equals(null),永远返回是“false”,x.equals(和x不同类型的对象)永远返回是“false”
  • 示例
public class OrderTest {
    public static void main(String []args) {
        Order c1 = new Order(10,'aa');
  	Order c2 = new Order(10,'bb');
  	Order c3 = new Order(10,'aa');
  	System.out.println(c1.equals(c2));  //false
  	System.out.println(c1.equals(c3));  //true
    }
}
class Order{
 	private int age;
 	private String name;
 	public Order(int age,String name){
  		this.age = age;
 		this.name = name;
 	}
 	public void setAge(int age){
  		this.age = age;
 	}
 	public int getAge(){
  		return age;
 	}
 	public void setName(String name){
  		this.name = name;
 	}
 	public String getName(){
  		return name;
 	}
 	public boolean equals(Object obj){   //手动实现equals的重写
  		if(this == obj){
   			return false;
  		}
  		if(obj instanceof Order){
   			Order order = (Order)obj;
   			return this.age == order.age && this.name.equals(order.name);// 注意引用类型比较的时候还是要调用equals而不是直接用==
  		}
  		return false;
 	}
}

4.2.2 toString() 方法的使用

  • Object 类中的 toString()
    • 输出一个引用对象时,实际上就是调用当前对象的 toString()
    • 定义:public String toString(){return getClass().getName() + "@" + Integer.toHexString(hashCode());}
    • 像String、Date、File、包装类等都重写了 Object 类中的 toString() 方法,使得在调用 toString() 时,返回"实体内容"信息
    • 自定义类如果重写 toString() 方法,当调用此方法时,返回对象的"实体内容"

五、包装类(Wrapper)的使用

5.1 单元测试方法的使用

  • JUnit 单元测试的步骤
    • 选中当前项目工程 --》 右键build path --》 add libraries --》 JUnit 4 --》 下一步
    • 创建一个 Java 类进行单元测试,此时的 Java 类要求:此类是公共的;此类提供一个公共的无参构造器
    • 此类中声明单元测试方法,此时的单元测试方法要求:方法的权限是 public;没有返回值;没有形参
    • 此单元测试方法上需要声明注解:@Test,并在单元测试类中导入 import org.junit.Test;
    • 声明好单元测试方法以后,就可以在方法体内测试代码
    • 写好代码后,左键双击单元测试方法名:右键 --》 run as --》 JUnit Test
  • 说明:如果执行结果无错误,则显示是一个绿色进度条,反之,错误即为红色进度条
  • 实际开发过程中:直接 @Test,报错时选中对应包导入即可

5.2 包装类的使用

  • 8种基本数据类型对应的包装类
基本数据类型byteshortintlongfloatdoublebooleanchar
包装类ByteShortIntegerLongFloatDoubleBooleanCharacter
  • 说明:其中 Byte、Short、Integer、Long、Float、Double 的父类是 Number

5.3 包装类与基本数据类型相互转换

  • 基本数据类型和包装类
    + 基本数据类型 ----> 包装类(装箱):调用包装类的构造器;通过字符串参数
    + 包装类 ----> 基本数据类型:调用包装类Xxx方法 xxxvalue()
    + 示例:
public class WrapperTest {
    public static void main(String []args) {
        // 基本数据类型转换为包装类
  	@test
  	public void test1(){
   		int num1 = 10;
  		// System.out println(num1.toString()); num1是基本数据类型,报错
   		Integer in1 = new Integer(num1);  //调用包装类的构造器
   		System.out println(in1.toString());
   
   		Integer in2 = new Integer("123");  //通过字符串参数
   		System.out println(in2.toString()); 
   
  		// Integer in3 = new Integer("123abc");  //报异常
  		// System.out println(in3.toString());   
   
   		Boolean b1 = new Boolean(true);  //true
   		Boolean b2 = new Boolean("true"); //true
   		Boolean b3 = new Boolean("true123");  //不报异常,输出false
   
   		Order order = new Order();
   		System.out println(Order.isMale);  //输出默认值false
   		System.out println(Order.isFemale);   // 输出默认值null
  	}
    	// 包装类转换为基本数据类型
  	@test
  	public void test2(){
   		Integer in3 = new Integer("123");
   		int i3 = in3.intValue();   //调用包装类Xxx方法 xxxvalue()
   		System.out.println(i3 + 1); 
   
   		Float f1 = new Float(12.3f);
   		float f2 = f1.floatValue(); //同理
   		System.out.println(f2 + 1); 
  	}
    }
}
class Order{
 	boolean isMale;
 	Boolean isFemale;
}

补充说明:JDK 5.0以后具有自动装箱与自动拆箱的新特性

int num2 = 10;
Integer in1 = num2;//自动装箱
  
boolean b1 = true;
Boolean b2 = b1;//自动装箱
    
System.out.println(in1.toString());
int num3 = in1;//自动拆箱
  • 基本数据类型、包装类和 String 类相互转换
    + 基本数据类型、包装类 ----> String 类:调用String重载的valueOf(Xxx xxx)
    + String 类 ----> 基本数据类型、包装类:调用对应包装类的parseXxx()
public class WrapperTest {
    public static void main(String []args) {
        // 基本数据类型、包装类转换为String类型:调用String重载的valueOf(Xxx xxx)
  	@test
  	public void test1(){
   		int num1 = 10;
   		String str = num1 + "";  //方式1,连接运算
   		System.out.println(str);
   		
   		float f1 = 12.3f;
   		String str2 = String.valueOf(f1);  //方式2,调用valueOf方法输出"12.3"
   		System.out.println(str2);
   		
   		Double d1 = new Double(12.4);
   		String str3 = String.valueOf(d1);
   		System.out.println(str3);
  	}
  	// String类型转换为基本数据类型、包装类:调用包装类的parseXxx()
  	@test
  	public void test2(){
   		String str4 = "123";
   		int num2 = Integer.parseInt(str4);
   		System.out.println(num2 + 1); 
   		
   		String str5 = "true123";
   		Boolean b1 = Boolean.parseBoolean(str5);
   		System.out.println(b1); 
  	}
    }
}

六、static 关键字

6.1 static 修饰属性、方法、代码块、内部类

  • static 含义:静态的,可以用来修饰:属性、方法、代码块、内部类
  • static 修饰属性,得到静态变量(或类变量)
    • 是否使用 static 修饰,又分为静态属性 VS 非静态属性(实例变量)
      • 实例变量:创建类的多个对象,每个对象都独立的拥有了一套类中的非静态属性,当修改一个对象中非静态属性时,不会导致其他对象中同样的属性值的修改
      • 静态变量:创建了类的多个对象,多个对象共享同一个静态变量。当通过静态变量去修改某一个变量时,会导致其他对象调用此静态变量时,是修改过的
    • 静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用
    • 静态变量的加载要早于对象的创建
    • 由于类只会加载一次,则静态变量在内存中也只会存在一次。存在方法区的静态域中
    • 类可以调用类变量,不能调用实例变量;对象可以调用类变量、实例变量
  • static 修饰方法,得到静态方法
    • 随着类的加载而加载,可以通过"类.静态方法"的方式调用
    • 类可以调用静态方法,不能调用非静态方法;对象可以调用静态方法、非静态方法
    • 静态方法中,只能调用静态的方法或属性;非静态的方法中,可以调用所有的方法或属性
    • 在静态的方法内,不能使用 this 关键字、super 关键字
  • static 使用场景
    • 属性:属性是可以被多个对象所共享的,不会随着对象的不同而不同的;类中的常量也常常声明为 static
    • 方法:操作静态属性的方法,通常设置为 static;工具类中的方法,习惯上声明为 static 的。比如:Math、Arrays、Collections

6.2 应用----单例 (Singleton) 设计模式(重)

  • 单例 (Singleton) 设计模式定义:采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例
  • 单例模式实现方法
    • 饿汉式
      • 步骤:私有化类的构造器 —> 内部创建类的对象 —> 要求此对象也必须声明为静态的 —> 声明 public、static 的返回当前类对象的方法
      • 优缺点:线程安全;对象加载时间过长
    • 懒汉式
      • 步骤:私有化类的构造器 —> 声明当前类对象,没有初始化 —> 要求此对象也必须声明为静态的 —> 提供公共的静态的方法,返回类的对象
      • 优缺点:延迟对象的创建;目前的写法,会线程不安全(到多线程内容时,再修改)
public class SingletonTest {
    public static void main(String []args) {
        Bank bank1 = Bank.getInstance();//调用
  	Bank bank2 = Bank.getInstance();//bank1和bank2是同一个对象
    }
}
class Bank{
 	private Bank(){   //私有化类的构造器
 	}
 
 	//饿汉式:内部创建类的对象,要求此对象也必须声明为静态的;
 	//提供公共的静态的方法,返回类的对象
 	private static Bank instance = new Bank();
 	public static Bank getInstance(){
  	return instance;
 	}
 	//懒汉式:声明当前类对象,没有初始化,要求此对象也必须声明为静态的;
 	//提供公共的静态的方法,返回类的对象
 	private static Bank instance = null;
 	public static Bank getInstance(){
  		if(instance == null){
   			instance = new bank();
  		}
  		return instance;
 	}
}
  • 单例模式应用场景
    • 网站的计数器,一般也是单例模式实现,否则难以同步
    • 应用程序的日志应用,一般都使用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加
    • 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源
    • 项目中,读取配置文件的类,一般也只有一个对象。没有必要每次使用配置文件数据,都生成一个对象去读取
    • Application 也是单例的典型应用
    • Windows 的 Task Manager (任务管理器) 就是很典型的单例模式
    • Windows 的 Recycle Bin(回收站) 也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例

七、final 关键字

  • final 含义:最终的,可以用来修饰的结构包括类、方法、变量
  • final 修饰类:此类不能被其他类所继承,比如 String类、System类、StringBuffer类
  • final 修饰方法:此方法不能被子类重写,比如 Object类中的 getClass()
  • final 修饰变量:此时的变量(成员变量或局部变量)就是一个常量名称大写,且只能被赋值一次
    • 成员变量: 可以考虑赋值的位置有显式初始化、代码块中初始化、构造器中初始化
    • 局部变量:尤其是使用 final 修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值
  • static final 用来修饰属性,称为全局常量

八、abstract 关键字

8.1 abstract 修饰类、方法

  • abstract 含义:抽象的,可以用来修饰的结构包括类、方法
  • abstract 修饰类 ---- 抽象类
    • 此类不能实例化
    • 抽象类中一定有构造器,便于子类实例化时调用(涉及子类对象实例化全过程)
    • 开发中,都会提供抽象类的子类,让子类对象实例化,实现相关的操作
  • abstract 修饰方法 ---- 抽象方法
    • 抽象方法,只有方法的声明,没有方法体public abstract void eat();
    • 包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法
    • 若子类重写了父类中所有的抽象方法,此子类可实例化;若子类没有重写了类中所有的抽象方法,则子类也是抽象类,需要用 abstract 修饰
  • abstract 注意点:不能用来修饰变量、代码块、构造器;不能用来修饰私有方法、静态方法、final 的方法、final 的类

8.2 创建抽象类的匿名子类对象

// 抽象类
abstract class Creature{
 	public abstract void breath();
}
// 抽象类
abstract class Person extends Creature{
 	String name;
 	int age;
 	public Person(){ 
 	}
 	public Person(String name,int age){
  		this.name = name;
  		this.age = age;
 	}
 	public abstract void eat();  //抽象方法
 	public void walk(){
  		System.out.println("人走路");
 	}
}
// 子类:重新了父类所有的抽象方法
class Worker extends Person{
 	@Override
 	public void eat() {
 	}
 	@Override
 	public void breath() {
 	}
}
//测试
public class PersonTest {
    public static void main(String []args) { 
  	Worker worker = new Worker(); 
  	method1(worker); //非匿名的类非匿名的对象
  	method1(new Worker()); //非匿名的类匿名的对象
  	System.out.println("*********************");
  	//创建匿名子类的对象:p
  	Person p = new Person(){
   		@Override
   		public void eat() {
    			System.out.println("吃东西");
   		}
   		@Override
   		public void breath() {
    			System.out.println("呼吸空气");
   		}
  	};
  	method1(p);
  	System.out.println("**********************"); 
  	//创建匿名子类的匿名对象
  	method1(new Person(){
   		@Override
   		public void eat() {
    			System.out.println("吃零食");
   		}
   		@Override
   		public void breath() {
    			System.out.println("云南的空气");
   		}
  	});
    }
    public static void method1(Person p){
  	p.eat();
  	p.walk();
    }
}

8.3 应用 ---- 模板方法设计模式

  • 含义:软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现,这就是一种模板模式
  • 示例
// 抽象类
abstract class Template{
 	//计算某段代码执行所需花费的时间
 	public void sendTime(){
  		long start = System.currentTimeMillis();
  		code(); //不确定部分,易变的部分
  		long end = System.currentTimeMillis();
  		System.out.println("花费的时间为:" + (end - start));
 	}
 	public abstract void code();
	}
}
class SubTemlate extends Template{
 	@Override
 	public void code() {
  		for(int i = 2;i <= 1000;i++){
   			boolean isFlag = true;
   			for(int j = 2;j <= Math.sqrt(i);j++){
    				if(i % j == 0){
     				isFlag = false;
     				break;
    				}
   			}
   			if(isFlag){
    				System.out.println(i);
   			}
  		}
 	}
}
public class TemplateTest {
 	public static void main(String[] args) {
  		SubTemlate t = new SubTemlate();
  		t.sendTime();
 	}
}

九、interface 接口

9.1 接口的概述

  • 接口理解:继承是一个是不是的关系,而接口实现则是能不能的关系
  • 接口使用:使用 interface 来定义,接口和类是并列的两个结构
  • 接口定义
    • JDK7 及以前:只能定义全局常量和抽象方法
      • 全局常量:public static final 的,但是书写中,可以省略不写
      • 抽象方法:public abstract 的,也可以省略
    • JDK8:除了全局常量和抽象方法之外,还可以定义静态方法、默认方法(后面补充)
  • 接口实现
    • 接口中不能定义构造器!意味着接口不可以实例化
    • 接口通过让类去实现(implements)的方式来使用
      • 实现类覆盖了接口中的所有方法,则此实现类就可以实例化
      • 实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类
  • 接口的多实现和继承性
    • 多实现:Java 类可以实现多个接口,弥补了 Java 单继承性的局限性,格式是:class AA extends BB implementd CC,DD,EE
    • 多继承:接口与接口之间是继承,而且可以多继承,格式是:interface AA extends BB, CC,DD
  • 其它: 接口的具体使用,体现多态性,接口的主要用途就是被实现类实现。(面向接口编程);接口,实际可以看作是一种规范
// 接口定义
interface Flayable{
 	//全局变量
 	public static final int MAX_SPEED = 7900; 
 	int MIN_SPEED = 1;//省略了 public static final 
 	//抽象方法
 	public abstract void fly();
 	void stop();//省略了 public abstract
}
// 接口通过类实现
class Plane implements Flayable{
 	@Override
 	public void fly() {
  		System.out.println("飞机通过引擎起飞");
 	}
 	@Override
 	public void stop() {
  		System.out.println("驾驶员减速停止");
 	}
}

9.2 接口的应用:代理模式(Proxy)

// 接口
interface Star {
 	void confer();// 面谈
 	void signContract();// 签合同
 	void bookTicket();// 订票
 	void sing();// 唱歌
 	void collectMoney();// 收钱
}
//被代理类 --- 明星本人
class RealStar implements Star {
 	public void confer() {
 	}
 	public void signContract() {
 	}
 	public void bookTicket() {
 	}
 	public void sing() {
  		System.out.println("明星:歌唱~~~");
 	}
 	public void collectMoney() {
 	}
}
//代理类  --- 经纪人
class Proxy implements Star {
 	private Star real;
 	public Proxy(Star real) {
  		this.real = real;
 	}
 	public void confer() {
  		System.out.println("经纪人面谈");
 	}
 	public void signContract() {
  		System.out.println("经纪人签合同");
 	}
 	public void bookTicket() {
  		System.out.println("经纪人订票");
 	}
 	public void sing() {
  		real.sing();
 	}
 	public void collectMoney() {
  		System.out.println("经纪人收钱");
 	}
}
public class StaticProxyTest {
 	public static void main(String[] args) {
  		Proxy s = new Proxy(new RealStar());
  		s.confer();
  		s.signContract();
  		s.bookTicket();
  		s.sing();
  		s.collectMoney();
 	}
}

9.3 接口的应用:工厂模式(略)

9.4 Java 8 中关于接口的改进

JDK8:除了全局常量和抽象方法之外,还可以定义静态方法、默认方法(略)

  • 静态方法:使用 static 关键字修饰,接口中定义的静态方法,只能通过接口来调用
  • 默认方法:使用 default 关键字修饰,通过实现类的对象,可以调用接口中的默认方法,如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法
  • 类优先原则:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法
  • 接口冲突:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,那么在实现类没有重写此方法的情况下,报错,这就需要我们必须在实现类中重写此方法
  • 如何在子类(或实现类)的方法中调用父类、接口中被重写的方法
    + 父类:super.method3()
    + 接口:CompareA.super.method3()

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值