JAVA知识点全面总结6:泛型反射和注解
六.JAVA知识点全面总结6泛型反射和注解
1.什么是泛型?可以用在哪里?
2.泛型擦除机制是什么?为什么擦除?
3.通配符是什么?作用是什么?
未更新
1.注解是什么?有什么用?
2.注解的自定义和实现机理是什么?
3.JAVA编译过程是什么?
未更新
1.什么是反射?反射的用处?
2.反射的结构?
3.反射在编译和运行时的理解
未更新
未更新
六.JAVA知识点全面总结6泛型反射和注解
1.什么是泛型?可以用在哪里?
①编译器行为
- 编译器可以对泛型参数进行检测,增强代码的可读性或稳定性。
②用法
- 泛型类: public class Person<T>{ }
- 泛型接口:public interface Person<T>{}
- 泛型方法:public static <E> void print(E[ ] array){}
③项目中
- 通用的返回结果
- 工具类
④泛型代码
- 通用的返回结果
package fanxingtest;public class CommonResult<T> {private String code;//返回状态码private T data;//返回数据private String message;//返回信息public CommonResult(String code, T data, String message) {this.code = code;this.data = data;this.message = message;}public String getCode() {return code;}public T getData() {return data;}public String getMessage() {return message;}public void setCode(String code) {this.code = code;}public void setData(T data) {this.data = data;}public void setMessage(String message) {this.message = message;}@Overridepublic String toString() {return "CommonResult{" +"code='" + code + '\'' +", data=" + data +", message='" + message + '\'' +'}';}
}
2.泛型擦除机制是什么?为什么擦除?
①泛型擦除机制
- 用于编译器类型检查,编译时擦除信息(编译器行为)
- 不是真的泛型,为了兼容老版本,故引入泛型机制但不创建新的类型
②泛型擦除机制简介
- List<T> 编译器擦除为 List
- E[ ] Array 编译器擦除为 Object[] Array
- 可通过反射调用方法来存其他类型(证明是编译时行为),例如List<Integer>通过反射可以存储String类型的变量
③编译过程
- java编译器先检查泛型的类型,然后擦除类型,再编译
④泛型使用限制
- 泛型参数不能传入基本数据类型,需要时Object的子类(擦除为Object)
- 不能用static修饰泛型类中变量或方法(泛型),但可以在静态方法中加入泛型变为泛型方法。
原因是能否通过类.方法调用。如果是泛型类中的静态成员变量,那么调用类.方法仍然确定不了泛型变量。如果是静态方法中加入泛型,那么类.方法也可确定泛型变量。 - 区分泛型类中的方法和静态泛型方法
Class Person<T> {static T eat(){ }}泛型类中的静态方法不可行
Class Person<T>{static <k> void eat(K a){ }}泛型类中的静态泛型方法可行
⑤代码示例
- 泛型擦除机制检验
package fanxingtest;import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Iterator;public class CaChuTest {public static void main(String[] args) throws Exception{HashSet<Integer> integers = new HashSet<>();integers.add(1);//得到hashset中的数为1System.out.println(integers.iterator().next());//利用反射插入String类型的数//此时输出1,"abc",故验证泛型是擦除类型的//注意泛型获得方法对象要加入参数(add是泛型T的方法,运行时擦除为Object类型)Class aClass = integers.getClass();Method add1 = aClass.getDeclaredMethod("add",Object.class);add1.invoke(integers,"abc");Iterator iterator = integers.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}}
}
- 泛型类的静态方法和静态泛型方法
package fanxingtest;public class StaticFanxinTest {}
class People<T>{//编译器报错static T data;//编译器报错static T print(){System.out.println("你好");return T t;}//编译器可运行static <K> void print(K k){System.out.println("你好"+k);}
}
3.通配符是什么?作用是什么?
①通配符使用与子类泛型不能赋值给父类泛型,解决多态不能用于泛型。
List<People> = List<Man> 编译不过 子类泛型不能赋值给父类泛型
List<?> = List<Man> 利用通配符 编译过
②对比
- T 声明变量 类或方法 Object泛型擦除
- ?不能声明 <?> 捕获类型
③通配符的使用
- ? extends A 赋值A或A的子类 可读不可写(子类可能单独的结构)
- ? super B 赋值B或B父类 可写可读(结构都有)
- 注意:赋值时通配符在左,变量在右
- 注意:泛型类型相同,类可使用多态
④代码解释
package fanxingtest;import java.util.*;public class TongPeiFuTest {public static void main(String[] args) {//泛型相同,类不同为子类父类,可以多态HashSet<Integer> integers = new LinkedHashSet<Integer>();//类相同,泛型为子类父类不可以多态,编译出错LinkedHashSet<Exception> integers1 = new LinkedHashSet<RuntimeException>();//类相同,使用通配符,编译过LinkedHashSet<?> integers2 = new LinkedHashSet<RuntimeException>();//通配符Set<? extends HashSet> ext = null;Set<? super HashSet> sut = null;Set<Set> c = null;Set<HashSet> d = null;Set<LinkedHashSet> e = null;ext = c;//编译不过 必须是子类或同级ext = d;//编译过ext = e;//编译过sut = c;//编译过sut = d;//编译过sut = e;//编译不过,必须是父类或同级//可读不可写ext.add(new HashSet());//编译不过Iterator<? extends HashSet> iterator = ext.iterator();iterator.next();//可写可读sut.add(new HashSet());Iterator<? super HashSet> iterator1 = sut.iterator();iterator1.next();}
}
未更新
1.注解是什么?有什么用?
①注解
- 注解用于修饰类,方法,变量,提供在编译或运行时使用
②时间
- 编译器扫描
@override 编译器检查是否重写
@data 编译器加入代码 - 运行期反射处理
@component 通过反射处理具体逻辑(处理器)
③定义
- 系统定义注解
@override
@deprecated - 自定义注解
④元注解(注解的注解)
- @Retention 声明生命周期(自定义注解一般声明为Runtime)
- @Target 声明作用的目标
- @Documented 添加信息到文档
- @Inherited 子类自动继承此注解的注解
2.注解的自定义和实现机理是什么?
①@overide
- 功能:重写的方法
- JVM:在字节码层面实现了该功能
②自定义注解
- 自定义注解
- 实现注解处理逻辑(注解处理器:利用反射处理注解)
- javac注册注解处理器为jvm处理器(会在运行时运行注解处理器)
③代码
- 注解实现检查年龄大于10的孩子有几个
package annotationtest;import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Field;public class CheckAgeTest {public static void main(String[] args) {MySchoole mySchoole = new MySchoole();try {CheckAge(mySchoole);} catch (Exception e) {e.printStackTrace();}}static void CheckAge(Object o) throws Exception{Class aClass = o.getClass();int num = 0;Annotation[] annotations = aClass.getAnnotations();for(int i = 0;i < annotations.length;i++){if(annotations[i].annotationType()==Check.class){Field[] declaredFields = aClass.getDeclaredFields();for(int j = 0;j<declaredFields.length;j++){if((Integer)declaredFields[j].get(o)>=10){num++;}}}}System.out.println("班级里一共有"+num+"个大于10岁的小孩子");}
}@Retention(RetentionPolicy.RUNTIME)
@interface Check{
}@Check
class MySchoole{int age1 = 11;int age2 = 13;int age3 =9;int age4 = 12;
}
3.JAVA编译过程是什么?
- 解析与填充符号表
- 插入注解处理器并执行注解处理过程
- 分析与字节码的生成
未更新
1.什么是反射?反射的用处?
①反射
- 运行时分析类以及执行类的方法,通过反射获得任何一个类的所有属性和方法,且不知道处理的类是什么(Object)
②用处
- 例子:不想修改代码,只想修改配置
- 例子:代码复用,写一次注解直接多次使用且方便
③举例
- @data lombak(注解 + 反射)
正常写需要每次添加get set方法
反射写,获取注解的类,动态添加get set方法生成.class文件 - properties (配置文件 + 反射)
正常写,每次需要直接修改代码
反射写,每次只需要修改配置。
④代码
- 配置+反射 动态运行代码
//注意:java获取本模块内类的结构用全限定名(包名+类名)(且类必须是public类)
//此时src/下相当于是类路径,即jvm执行class时从类路径下寻找(包名+类名)classname=annotationtest.MyMethod
methodname=saypackage annotationtest;import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.util.Properties;public class PeiZhiTest {public static void main(String[] args) throws Exception{FileInputStream fileInputStream = new FileInputStream("day02/src/annotationtest/method.properties");Properties properties = new Properties();properties.load(fileInputStream);String name1 = properties.getProperty("classname");String name2 = properties.getProperty("methodname");Class aClass = Class.forName(name1);Method declaredMethod = aClass.getDeclaredMethod(name2);declaredMethod.invoke(aClass.newInstance());}}
class MyMethod{void say(){System.out.println("反射调用方法say");}void walk(){System.out.println("反射调用方法walk");}
}
2.反射的结构?
①反射
- Class类:加载到内存的运行时类,都有一个Class的实例
- Class类继承Object类,Class实例能表示运行的Object类
②使用的反射
- 获取Class实例
运行时类的静态属性Class clazz = Person.Class;
运行时类的非静态方法 Class clazz = Person.getClass;
Class类的静态方法 Class clazz = Class.forName(“”); - 创建运行时类的对象
Object o = clazz.newInstance(); - 获取运行时类的结构
clazz.getDeclaredMethods(); - 获取具体方法和具体属性对象
Filed age = clazz.getDeclareFiled(“age”); age.set(o,12);
Method mh = clazz.getDeclareMethod(“show”);show.invoke(o); - 注意
Class的实例不能访问私有结构
Class的实例获得方法时有形参需要加形参,不加默认无形参
3.反射在编译和运行时的理解
①多态
- Person p = new Man()
编译期间:允许
运行期间:子类方法覆盖父类方法(实际上为父类引用指向子类的所有结构)
②反射
- Object obj = clazz.newInstance();method.invoke(obj);
编译期间:运行
运行期间:obj实际上指向为运行时类的实例
③多态+反射
- 即多态+反射可以让父类引用调用子类的私有结构
- 理解:父类引用指向的就是子类的类结构(重写了方法),但是父类引用直接调用子类独有的方法编译不过,故可通过反射调用。
- 代码
package reflecttest;import java.lang.reflect.Method;public class FuZiSiYouTest {public static void main(String[] args) throws Exception{Person p = new Man();Class aClass = p.getClass();Method eat = aClass.getDeclaredMethod("eat");//调用成功 结果为子类私有方法eat.invoke(aClass.newInstance());}
}class Person{}
class Man extends Person{void eat(){System.out.println("子类私有方法");}
}
④总结
- 运行时类Class的实例创建的对象都为Object(编译过)
- 在实际运行时Object指向原本类的结构,但不能直接调用(因为编译不过),需要运行时反射调用(编译过)
未更新
未更新
相关文章:

JAVA知识点全面总结6:泛型反射和注解
六.JAVA知识点全面总结6泛型反射和注解 1.什么是泛型?可以用在哪里? 2.泛型擦除机制是什么?为什么擦除? 3.通配符是什么?作用是什么? 未更新 1.注解是什么?有什么用? 2.注解的自定义和实…...

死代码删除(DCE,Dead Code Elimination)和激进的死代码删除(ADCE,Aggressive DCE)
死代码删除(DCE,Dead Code Elimination)和激进的死代码删除(ADCE,Aggressive DCE)死代码删除(DCE,Dead Code Elimination)DCE简介DCE基本算法激进的死代码删除࿰…...

询问new bing关于android开发的15个问题(前景、未来、发展方向)
前言:new bing是基于chat-gpt的新搜索工具,可以采用对话方式进行问题搜索,经过排队等候终于可以使用new bing,询问了目前我最关心的关于android开发几个问题 文章目录1.如何学好android开发?2.android开发能做什么?3.…...

【C++】初识类和对象
🏖️作者:malloc不出对象 ⛺专栏:C的学习之路 👦个人简介:一名双非本科院校大二在读的科班编程菜鸟,努力编程只为赶上各位大佬的步伐🙈🙈 目录前言一、面向过程和面向对象初步认识二…...

EPICS S7nodave手册
第一章:介绍 本手册分为6章(不算次介绍部分)。第一章介绍s7nodave用于EPICS的设备支持的概念和特新。第二章描述启动一个使用s7nodave的IOC项目所需要的几步。第三章描述s7nodave支持的IOC shell命令。之后,第四章解释s7nodave支持的各种记录类型。最后…...

2023最新版本RabbitMQ的持久化和简单使用
上节讲了 RabbitMQ下载安装教程 , 本节主要介绍RabbitMQ的持久化和简单使用。 一、RabbitMQ消息持久化 当处理一个比较耗时得任务的时候,也许想知道消费者(consumers)是否运行到一半就挂掉。在当前的代码中,当RabbitM…...

函数式编程
函数式编程(一) 文章目录函数式编程(一)1. 前言1.1 概念2. Lambda 表达式2.1 概述2.2 基本的格式2.3 触发条件2.4 Lambda表达式2.4.1 无参无返回值2.4.2 有参无返回值2.4.3 无参数有返回值2.4.4 有参有返回值【重点】2.4.4.1 比较…...

【Java 类】001-访问修饰符、命名规范
【Java 类】001-访问修饰符、命名规范 文章目录【Java 类】001-访问修饰符、命名规范一、访问修饰符概述1、是什么2、作用作用问题3、访问修饰符有哪些4、作用对象二、访问修饰符使用演示1、类访问修饰符演示第一步:创建 Dog 类:public第二步:…...

【C++】命名空间
🏖️作者:malloc不出对象 ⛺专栏:C的学习之路 👦个人简介:一名双非本科院校大二在读的科班编程菜鸟,努力编程只为赶上各位大佬的步伐🙈🙈 目录前言一、命名空间产生的背景二、命名空…...

【AutoSAR】【MCAL】Dio
一、结构 二、功能介绍 DIO(数字输入输出)驱动模块主要是对端口(Port),通道(Channel)和通道组(ChannelGroup)进行读写操作。 通道(Channel)&…...

瑞吉外卖——day2
目录 一、新增员工 二、查询分页数据 三、启用、禁用员工账户、编辑员工信息 一、新增员工 点击左上角新增员工 页面如下: 我们随便填数据 ,点击保存,请求的地址如下 返回前端可以看到请求方式为Post 在employeeController中编写对应的代…...

了解java
#常见编程语言介绍 C语言 C语言 java语言 javaScript语言 PHP语言 python语言Object-C和Swift语言 C# (c sharp)语言 Kotlin语言 Go语言 Basic语言 #JAVA的发展 起源于1991年SUN公司GREEN项目,1996年JDK1.0正式发布 后被Oracle公司收购&…...

【编程实践】代码之中有创意:“我一直认为工程师世界上最具创造性的工作之一”
代码之中有创意 “我一直认为工程师世界上最具创造性的工作之一”。 文章目录 代码之中有创意一、代码可以赋予创造力1.1 代码的创造力1.2 如何发挥代码的创造力二、有创意的代码可以提高工作效率2.1 代码创意可以提高工作效率2.2 如何利用代码创意来提高工作效率三、代码创意可…...

【MySQL】表连接
一、为什么要学习 因为不合理的使用连接会导致慢查询 二、什么是连接 参与连接的表叫做 连接表, 连接就是把 各个连接表 进行的组合 (笛卡儿积)加入结果集并返回 三、连接查询 如何只是对表进行大量的连接,笛卡儿积作用得到的…...

2023湖南省“楚怡杯”职业技能大赛“网络安全” 项目比赛任务书
2023湖南省“楚怡杯”职业技能大赛“网络安全” 项目比赛任务书2023安徽省“中银杯”职业技能大赛“网络安全” 项目比赛任务书A模块基础设施设置/安全加固(200分)A-1:登录安全加固(Windows, Linux)A-2:Ngi…...

Android应用启动优化笔记整理
应用启动相关流程与优化 应用启动主要涉及SystemServer进程 和 app进程。 SystemServer进程负责app进程创建和管理、窗口的创建和管理(StartingWindow 和 AppWindow)、应用的启动流程调度等。 App进程被创建后,进行一系列进程初始化、组件初…...

图像bytes字节串二进制转十六进制及bytes转为图像
目录前言正文二进制与十六进制的bytes互转读取bytes为图像法1:直接写入f.read的结果法2: 转换为PIL或Numpy前言 参考: 8. python基础之基础数据类型–bytes - CSDN python 16进制与图片互转 - CSDN 正文 二进制与十六进制的bytes互转 bytes保存的是原始的字节(二…...

信息安全与数学基础-笔记-②同余
知识目录同余完全剩余系剩余类完全剩余系❀简化剩余系❀欧拉函数逆元!欧拉定理 !同余 a,b 两个数字,都模m,当两个数字模m后余的数一样即为同余。 例子: a bq r (mod m),这里的a 和 r 就是同余 ÿ…...

网络安全法
目录正文第一章第二章第三章第四章第五章第六章 法律责任第七章 附则正文 学习网络安全应该知道网络安全法 第一章 总则 第一条: 为了保障网络安全,维护网络空间主权和国家安全、社会公共利益,保护公民、法人和其他组织的合法权益,促进经济…...

django框架开发部署项目
前言:相信看到这篇文章的小伙伴都或多或少有一些编程基础,懂得一些linux的基本命令了吧,本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python:一种编程语言&…...

Unity记录1.3-入门-第一阶段总结
文章首发及后续更新:https://mwhls.top/4447.html,无图/无目录/格式错误/更多相关请至首发页查看。 新的更新内容请到mwhls.top查看。 欢迎提出任何疑问及批评,非常感谢! 汇总:Unity 记录 摘要:第一阶段的总…...

Linux入门篇-文件管理
简介 简单的文件管理。 ⽂件内容的查看 ⽂本⽂件内容的查看 cat ⽂本⽂件的path1 ⽂本⽂件的path2 head ⽂本⽂件的path ,显示⽂件的前10⾏内容 head -n 5 ⽂本⽂件的path , 显示⽂件的前5⾏内容 head -5 等于head -n 5tail ⽂本⽂件的path, 显示⽂件的后10⾏内容…...

如何从错误中成长?
在上一篇文章“技术人的犯错成本”里,我和你聊了技术人可能会犯的各式各样的错误,也举了很多例子,说明了技术人犯错的成本。在竞争激烈的互联网时代,试错当然是好事,但了解错误成本,避免不应该犯的错误&…...

谈谈一个程序员的职场心得(真有用)
谈谈一个程序员的职场心得 我会分为三个部分:软件开发,职场协作和认知成长,每个部分精简成 7 条心得。 软件开发 若无必要,勿增实体。 这是奥卡姆剃刀的定义,所谓剃刀就是法则,是奥卡姆这个英国学者提出来…...

Pytest:一个卓有成效的测试工具
大家都知道,目前最流行的Python单元测试框架有三种,分别是unittest, nose和pytest。其中unittest是Python自带的测试框架,但问题是比较老了,赶不上时代发展了(哈哈哈);nose2定位是带插件的unitt…...

Compose 动画 (三) : AnimatedVisibility 从入门到深入
1. AnimatedVisibility 是什么 AnimatedVisibility可以实现Compose组件的显示和隐藏,并且可以指定显示/隐藏时候的动画效果。(EnterTransition/ExitTransition) 和 animateXxxAsState、animateContentSize、Crossfade、AnimatedContent 这几个API一起,都…...

网络基础(二)
目录 应用层 再谈 "协议" 协议是一种 "约定". socket api的接口, 在读写数据时, 都是按 "字符串" 的方式来发送接收的. 如果我们要传输一些"结构化的数据" 怎么办呢? 为什么要转换呢? 如果我们将struct message里面…...

Java线程知识点总结
文章目录Java 线程基础线程简介什么是进程什么是线程进程和线程的区别创建线程ThreadRunnableCallable、Future、FutureTaskCallableFutureFutureTaskCallable Future FutureTask 示例线程基本用法线程休眠线程礼让终止线程守护线程线程通信wait/notify/notifyAlljoin管道线程…...

数据结构——第三章 栈与队列(4)
队列的应用1.基于队列的医院挂号模拟系统2.队列的运用1.基于队列的医院挂号模拟系统 代码实现分享 2.队列的运用 问题描述:某运动会设立N个比赛项目,每个运动成员可以参加1~3个项目。试问如何安排比赛日程,既可以使同一运动员参加的项目不…...

华为机试HJ73-计算日期到天数转换
HJ73 计算日期到天数转换 题目描述: 描述 根据输入的日期,计算是这一年的第几天。 保证年份为4位数且日期合法。 进阶:时间复杂度:O(n) ,空间复杂度:O(1) 输入描述: 输入一行,每行…...