美文网首页
接口(interface)

接口(interface)

作者: Finlay_Li | 来源:发表于2019-04-01 18:14 被阅读0次

定义

可以把接口理解为更彻底的抽象类。

如何使用接口

  • 接口与类是平级的也会编译为.class文件
  • 关键字
    interface
  • 声明
    public interface Flyer{ }

接口的规则

  • 接口中只有“全局静态常量”和“抽象方法"
  1. 全局静态常量
public static final int NUM = 100;  

接口中的所有成员变量都默认是由public static final修饰。

  1. 抽象方法
public abstract  void fly();    

接口中的所有方法都默认是由public abstract修饰。

因此interface不能创建实例 (无构造器)
所以interface用以定义行为,被class实现(面向接口编程)
关键字: implements
实现:class Bird implements Flyer{}

  • 实现接口的类称为“实现类”
  1. 若实现类实现了接口中“所有”的抽象方法,该类为具体类
    若实现类没有实现接口中“所有”的抽象方法,该类必须是抽象类
  2. 接口可以继承接口,并且可以多继承接口,但是接口不能继承任何具体类
    因为任何的具体类都会有一般方法,所以接口不能继承任何类
  3. 类只能单继承,但可以同时实现多个接口
    class Bird extends Animal implements Flyer, Runner{ }
    注意:先继承,后实现(先写extends,后写implements)
  4. 接口支持多态

接口的作用

  • 类可以多实现接口,解决了 Java 中单继承的局限性
  • 接口定义了一种规范,可以定义一系列不相干事物的相同功能,大大提高了通用性

示例

public class InterfaceTest {
    
    public static void main(String[] args) {
        System.out.println(Flyer.NUM);
        
//        Flyer f = new Flyer();
        
        Bird bird = new Bird();
        bird.fly();
        
        System.out.println(Flyer.NUM);
        System.out.println(Runner.NUM);
        System.out.println(bird.num);
        
        Flyer f = new Bird(); //接口支持多态!
        f.fly(); //虚拟方法调用
        
    }
}

设计模式应用

  • 工厂方法(FactoryMethod)
  1. 作用:用于创建对象的接口
  2. 概述:
    FactoryMethod模式是设计模式中应用最为广泛的模式,在面向对象的编程中,对象的创建工作非常简单,对象的创建时机却很重要。
    FactoryMethod解决的就是这个问题,它通过面向对象的手法,将所要创建的具体对象的创建工作延迟到了子类,从而提供了一种扩展的策略
  • 代理模式(Proxy):宝强和宋吉

动态代理:
简单的说:
在启动核心方法时,拦截,在代理开始前后,做事情。
没有浸入到方法内部,却可以修改实际方法的任何细节。
比如:
在执行器中。返回个假结果。此时。另一头的核心方法执行时,将会拿到假结果。
也因为拦截,就可以在核心逻辑方法执行前,做其他辅助操作。使得核心逻辑方法可以
只编写核心的逻辑代码,完全解耦合。解决了硬编码的问题。
好处:完全解耦;
缺点:
1)实现复杂;不会写。
2)jdk提供的动态代理,被代理对象一定要实现接口;否则无法创建动态代理;
因为代理对象要代理对象的方法,并且,代理对象和被代理对象唯一的联系,就是接口!

package com.atguigu.inter;
/**

  • 动态代理项目:计算器
  • @author Mr.L

*/
public interface Calculator {

 public int add(int i,int j);
 public int sub(int i,int j);
 public int mul(int i,int j);
 public int div(int i,int j);

}
package com.atguigu.inter;
/**

  • 项目:数学计算器+日志辅助
  • @author Mr.L

*/
public class MathCalculator implements Calculator {
@Override
public int add(int i, int j) {
// 这输出就是日志辅助。但是目前我不得不硬编码在核心逻辑中。
// 如果,我还需要更加多的日志输出,将导致核心逻辑方法中,却编写了一大截无相关的代码。
System.out.println("运算开始了...");

      int result=i+j;

// 这输出就是日志辅助。但是目前我不得不硬编码在核心逻辑中。
System.out.println("===>实际的内部add方法执行了:"+result);
return result;
}
@Override
public int sub(int i, int j) {
int result=i-j;
return result;
}
@Override
public int mul(int i, int j) {
int result=i*j;
return result;
}
@Override
public int div(int i, int j) {
int result=i/j;
return result;
}
}

package com.atguigu.test;
import org.junit.Test;
import com.atguigu.inter.Calculator;
import com.atguigu.inter.MathCalculator;
import com.atguigu.proxy.CalculatorProxyFactory;
public class AOPTest {

 /**
  * 使用动态代理,以完全解耦合,执行数学计算器。
  * 1.活可以干好
  * 2.核心逻辑方法中,只有核心逻辑代码。完全解耦合
  * 3.执行实际方法时,可以做更多的事情。
  *    可以改变实际方法的任何细节。瞒天过海。
  */
 @Test
 public void test1() {
      //1.我们的实际对象
      Calculator calculator = new MathCalculator();
      //2.获取到的代理对象
      Calculator proxy = CalculatorProxyFactory.getProxy(calculator);
      
      //3.让代理对象帮忙干活
      int add=proxy.add(1, 2);
      System.out.println("计算结果:"+add);
 }
 
 
 /**
  * 日志辅助,硬编码在核心逻辑中测试。
  */
 @Test
 public void test() {
      Calculator calculator = new MathCalculator();
      int add = calculator.add(1, 2);
      System.out.println("计算结果:"+add);
 }

}

package com.atguigu.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import com.atguigu.inter.Calculator;
import com.atguigu.util.LogUtils;
/**

  • 代理工厂。帮我们生产代理对象。

  • @author Mr.L

  • 王宝强:Calculator calculator

  • 宋喆 :Calculator proxy
    */
    public class CalculatorProxyFactory {

    //1.返回一个传入的对象的代理对象。
    public static Calculator getProxy(final Calculator calculator) {

          //4:提供Proxy类需要的三个参数
          //①ClassLoader loader:被代理对象的类加载器
          ClassLoader loader = calculator.getClass().getClassLoader();
          
          //②Class<?>[] interfaces:被代理对象,所实现的所有接口
          Class<?>[] interfaces = calculator.getClass().getInterfaces();
      
          //③InvocationHandler handler :执行器
          //6。分析清楚代理与被代理对象关系:然后关键的执行器:在执行期间,代理对象可以通过invoke执行被代理的方法;
          InvocationHandler handler = new InvocationHandler() {
               
               
               /**
                * 7.分析并提供执行所需要的参数。
                * Object proxy:宋喆
                * Method method:正要执行的方法:执行实际方法
                * Object[] args:方法执行时传入的参数
                */
               @Override
               public Object invoke(Object proxy, Method method, Object[] args)
                         throws Throwable {
                    
                     Object result=null;
                      //System.out.println("代理对象要帮你调用方法了...");
                    try {
                           //9.1 方法开始的时候记录一下日志;
                         LogUtils.logStart(method, args);
                         
                         
                           //method对象利用反射执行被代理对象的方法。调用后会有一个返回值
                           //obj:被代理对象:你宋喆再牛,上台表演还得王宝强。
                         result = method.invoke(calculator, args);
                         
                              //9.2方法执行成功,返回值是多少。
                           LogUtils.logReturn(method, result);
                         
                    } catch (Exception e) {
                              
                              //9.3 如果出现异常了,输出e异常对象。
                         LogUtils.logException(method,e);
                              //甚至可以把异常都不输出。就算你1/0 照样给你定个结果。照样不报错6不6
                              //e.printStackTrace();
                              //return 10;
                    }finally {
                              //9.4 结束后。我就一定要你通知。
                         LogUtils.logEnd(method);
                    }
                    
                     
                     
                     
                     System.out.println(method.getName()+"方法正常返回,返回值:" + result);
                      //把真正执行的结果返回给外界。要不然宝强就给宋喆黑了。比如我不返回真的result.直接返回250.
                      return result;
                     
                     
                      //10。日志输出,以做好。但可以优化。把不同的日志提取。只在方法前后启动提取方法即可。
               }
          };
          
          
          //3。动态代理的核心是:使用反射下的Proxy类:返回一个指定接口的代理对象。
          //5。给了三个参数后,得到代理对象。返回。
          Object proxy = Proxy.newProxyInstance(loader, interfaces, handler);
 
      //2.放回一个代理对象。
      return (Calculator) proxy;
      
 }

}

package com.atguigu.util;
import java.lang.reflect.Method;
import java.util.Arrays;
/**

  • 日志优化
  • @author Mr.L

*/
public class LogUtils {

 //日志开始
 public static void logStart(Method method,Object[] args){
      System.out.println(method.getName()+"方法开始:参数表【"+Arrays.asList(args)+"】");
 }
 //日志方法正常返回
 public static void logReturn(Method method, Object result) {
      System.out.println(method.getName()+"方法正常返回:返回值:"+result);         
 }
 //日志记录异常
 public static void logException(Method method, Exception e) {
      System.out.println(method.getName()+"方法出异常了。异常信息:"+e);
 }
 //方法结束
 public static void logEnd(Method method) {
      System.out.println(method.getName()+"方法最终结束。");
 }  

}

静态代理:
特征:
代理类和目标对象的类都是在编译期间确定下来,不利于程序的扩展。
同时,每一个代理类只能为一个接口服务,如此程序开发中必然产生过多的代理。

如:
买房子                        买手机
买房功能        (接口)            买手机功能    (接口)
链家网(决定有房没房)    (代理类)            手机店/决定    (代理类)
买房者            (目标对象的类)        买手机者    (目标对象的类)
于是:
最好可以通过一个 代理类 完成全部的代理功能

相关文章

  • 接口

    interface 接口 implements 类实现接口 public interface 接口名{ 接口的成员...

  • 学习TypeScript 接口

    TypeScript 接口定义 interface interface_name {} 实例 联合类型和接口 接口...

  • java萌新入门之事件监听

    1.接口 1.1 接口的定义 定义接口的关键字:interface 格式: public interface 接口...

  • 2020-07-23(接口)

    1,接口特点 * a:接口用关键字interface表示, interface 接口名 {} * b:类实现接口用...

  • 2020-06-21接口

    接口 接口的特点 接口用关键字interface修饰:public interface 接口名{} 类实现接口用i...

  • java中的接口

    接口的特点: A:接口用关键字interface表示;格式:interface 接口名{}B:类实现接口用imp...

  • Java 接口(interface)

    接口用关键字interface表示格式:interface 接口名 {} 类实现接口用implements表示格式...

  • Java基础-接口

    1.接口的特点: A:接口用关键字interface表示 interface 接口名 {}B:类实现接口用i...

  • 接口(interface)

    建立一个User接口 建立UserImpl类 创建测试类 编译结果如下图

  • 接口(interface)

    接口(interface) 是与类并行的一个概念1.接口可以看做是一个特殊的抽象类。是常量与抽象方法的一个集合,...

网友评论

      本文标题:接口(interface)

      本文链接:https://www.haomeiwen.com/subject/lbhbbqtx.html