Java(面向对象--抽象类,接口,多态,代理--反射)

目录

一:抽象类

二 .接口

三:接口和抽象类的异同

四:多态

五:代理


一:抽象类

 *      概念:
 *          什么叫抽象类: 只要一个类 是abstract修饰的那么这个类就是抽象类
 *                      和 这个类中有没有抽象方法,没有必然的联系
 *  
 *          什么叫抽象方法:
 *                  方法由abstract修饰,并且没有方法体的方法    
 *  
 *          一个抽象类 是可以没有抽象方法;因为可能有抽象方法,所以这个类的作用不允许你创建对象(实例化)
 *      作用:
 *          不能创建对象,天生作为父类
 *          抽象类中的抽象方法有什么作用?
 *              1.抽象类中的抽象方法不是为了调用的
 *              2.为了强制子类去重写

二 .接口

1.接口的概念

 *         接口是功能的集合,就是方法的集合
 *         接口中只能定义方法,不能定义普通的成员变量
 * 
 *         而且接口中的成员方法,必须都是抽象的
 *         问题:接口能创建对象吗? 不能
 *             接口有什么用? 天生作为"父接口"
2.接口的定义
 *         定义类用关键字:class
 *         定义抽象类用关键字:abstract class
 *         定义接口用关键字:interface
 * 
 *         格式:
 *         public interface 接口名字{
 *             //成员变量,不能定义普通的成员变量
 *             //成员方法:必须都是抽象
 *             public abstract 返回值类型 方法名();
 *         }
4.各种类型之间的关系
 *         a.类和类之间:继承,而且是单继承,一个子类 只能有一个直接父类
 *         b.接口和接口之间:继承,但是可以多继承,一个子接口 可以有多个直接父接口
 * 
 *         面试题:java到底支不支持多继承?
 *             如果是类与类 不支持多继承,只支持多层继承
 *             如果是接口和接口 支持多继承,也支持多层继承
 *         c.类和接口之间: 不叫继承(extends),叫实现(implements),可以多实现
 *                     只有 类 实现 接口

5.接口中成员的特点
 *         成员变量,但是必须有固定修饰符 public static final 数据类型 变量= 值
 *         成员方法,必须是固定修饰符 public abstract 即 抽象方法

ps:固定修饰符 我们可以不写,但是不写不代表没有,编译器自动添加
 *         接口不可以创建对象(抽象类也是)
 *         实现类 以及 实现类接口 ,那么必须重写接口中所有的抽象方法,然后才能创建对象
 *             否则 这个实现类 还是一个抽象类,是不能创建对象的

三:接口和抽象类的异同

1.相同点:
 *         a.都不能创建对象
 *         b.都是作为父类/父接口
 *         c.子类/实现类 都必须重写抽象方法,然后才能创建对象
2.不同点:
 *         a.抽象类用关键字 abstract 接口用关键字interface
 *         b.抽象类中可以有抽象方法,可以没有抽象方法,也可以有部分是抽象方法,部分不是抽象方法
 *             接口中只要是方法,必须都是抽象的
 *         c.抽象类可以定义任意成员变量 接口的成员变量必须public static final修饰
 *         d.类和抽象类之间关系是单继承, 类和接口之间关系是多实现 
 *         e.思想上的区别
 *             1.抽象类中 必须定义  整个继承体系的共性内容

ps:继承遵循向上抽取原则,父类代表子类的共性。
 *             2.接口中定义 整个继承体系之外的 额外的 扩展的功能    

四:多态

指对象的多态
 *             一个对象 的多种状态
 *             比如: 一只狗  是狗,是动物,是生物
 *             比如: 一个人 是人,是动物,是生物
 *             比如: 你 在学校是学生,在家里是儿子,在公司员工,在外面老大

ps:通过父类引用指向子类对象,不同的子类可以呈现出不同的状态,就叫多态。
在java中的多态
 *             前提:
 *                 1.必须有子父类关系 (必须有继承)
 *                 2.必须有方法的重写
 *             多态在java中表现形式:
 *                 父类类型  变量名 = new 子类类型();
 *                 父类类型的变量 指向了  子类的对象

ps:多态的前提,有继承,有方法重写,有父类引用指向子类对象。

ps:父类引用可以是抽象父类,也可以是父接口。

静态多态:指在编译阶段出现的静态多态,通过方法的重载来达到。

动态多态:指在运行阶段出现的动态多态,通过方法的重写来达到。

注意事项:
 *         使用多态调用成员变量
 *              编译时 看父类 看左边
 *              运行时 看父类 看左边
 *         使用多态调用成员方法
 *             编译时 看父类 看左边
 *             运行时 看子类 看右边
 * 
ps:多态使用变量 编译运行都看父类,多态调用方法 编译看父类 运行看子类。

多态的弊端:
 *         多态只能调用子父类和子类共有的方法,不能调用子类特有的方法。

多态弊端的解决方法:

 *         向上向下转型:
 *             向上转型: 多态
 *             向下转型: 子类类型 变量名 =(子类类型)父类类型的变量;
 *                     变量名.子类特有方法();
ps:直接 向下转型过程中 很容易出现  类型转换的异常
 *         关键字:运算符 instanceof
 *             判断某一个对象 是不是属于一个类
 *             格式:
 *                  boolean b = 变量名 instanceof 类名

五:代理

动态语言:不需要编译,在运行阶段确定数据类型;静态语言,需要编译,在编译的时候就能确定数据类型。

 

反射:是在运行阶段可以获取整个类的方法,属性,构造函数。

获取Class对象:Class clazz=Class.forName("类的全路径"); (最常用)

创建对象的两种方法

         第一种:

         Class clazz=Class.forName("reflection.Person");默认需要有空的构造函数。

         第二种:

         Constructor c=clazz.getDeclaredConstructor(String.class,String.class,int.class); //创建对象并设置属性
         Person p1=(Person) c.newInstance("李四","男",20);

反射的应用场景:如果编译时根本无法预知该对象和类属于哪些类,程序只能依靠运行时的信息来发现该对象和类的真实信息,此时就必须使用到反射了。Person p=new Student();其中编译时类型为Person,运行时类型为Student。

反射总结:

          java从反射角度来说属于动态语言,所以说反射就是慢,在运行时候才能确定所属类,但是解决了编译时候无法确定所属类的问题。

 

代理分为静态代理和动态代理。代理就是使用实现类的方法把调用统一起来是对实现类的一个封装

  1.创建接口。

  2.创建多个实现类。

  3.创建一个代理。(类内部有接口对实现类的多态形式)

静态代理:自己手动编写代理类。

   第一步:
1 package ceshi1;
2 public interface Iuser {
3     void eat(String s);
4 }

       第二步:

1 package ceshi1;
2 public class UserImpl implements Iuser {
3   @Override
4   public void eat(String s) {
5     System.out.println("我要吃"+s);
6   }
7 }

         第三步:

 1 package ceshi1;
 2 public class UserProxy implements Iuser {
 3   private Iuser user = new UserImpl();
 4   @Override
 5   public void eat(String s) {
 6     System.out.println("静态代理前置内容");
 7     user.eat(s);
 8     System.out.println("静态代理后置内容");
 9   }
10 }

动态代理:自动生成代理类。

// 要被增强的对象
final NormalPerson p=new NormalPerson();
// 需求: 使用动态代理的方式对普通人进行增强
// jdk提供的类和方法可以给咱们动态的生成代理对象/增强对象 不需要自己去创建增强类
Person proxyPerson =(Person)Proxy.newProxyInstance(
	p.getClass().getClassLoader(), 
	p.getClass().getInterfaces(),
	new InvocationHandler() {
	/*参数概述 固定死的
	* 参数2: 要被增强的方法
	   * */
		@Override //invoke里面是所有的增强业务逻辑代码
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			if("eat".equals(method.getName()))
			{
				// 参数1:本身应该执行这个方法的对象
				method.invoke(p, args);
				System.out.println("增强了:变成飞...");
				return "abcd";
			}
			return method.invoke(p, args);
		}
	});
proxyPerson.run(); // 执行这个方法  invoke都会执行一遍   执行的内容就是针对该方法的增强

 

总结:

 静态代理:需要手动去实现代理类,非常不灵活。

动态代理:不用手动实现代理类,通过JDK或者cglib自动生成代理对象。

ps:代理类似于装饰者模式的思想。

JDK动态代理:必须要实现了接口的业务类才能用这种办法生成代理对象。新版本也开始结合ASM机制(利用字节码操作机制)。
cglib动态代理:基于ASM机制实现,通过生成业务类的子类作为代理类。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值