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:一种编程语言&…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...