当前位置: 首页 > news >正文

JAVA小白学习日记Day11

反射

1. 反射
反射是指在运行时检查、获取和修改类的属性、方法、构造方法等信息的能力,可以在运行时动态地创建对象、调用方法、访问属性,而不需要在编译时确定。

2. 获取类对象的三种方式
在代码中展示了三种获取类对象(Class对象)的方法:

通过类名获取类对象:
Class clazz = EasyClassA.class;这种方式直接使用类名后跟 .class 来获取对应的 Class 对象。

通过对象获取类对象:
clazz = new EasyClassA().getClass();通过创建类的实例,然后调用 getClass() 方法来获取其对应的 Class 对象。

通过 Class.forName() 方法获取:
clazz = Class.forName("com.easy725.EasyColor");使用类的全限定名(包括包名)作为参数,调用 Class.forName() 方法来动态获取该类的 Class 对象。

3. Class 类对象的作用
Class 类对象包含了与类相关的信息,如属性、方法、构造方法等的定义。Class类的对象是不能new的。反射的核心是Class类,程序中使用的类,每一个都有一个唯一对应的Class对象。
在运行时,Java 使用 Class 对象来表示和管理类的结构和元数据,允许在运行时检查和操作类。

package com.easy726;public class EasyClassA {//反射//有对象之前必须先有类,static来修饰类的属性和方法。//在java中存储了类的内容,这个内容也应该是一个对象。//java中每一个类都有一个内存,这每一块内存都是一个对象。//这些对象用来记录类中声明了哪些属性和方法以及构造方法。//java将这些类抽象为一个Class类。public static void main(String[] args) throws ClassNotFoundException {//Class类的对象是不能new的//获取类的类对象//1.通过类名获取类对象Class clazz=EasyClassA.class;//2.通过对象获取类对象clazz=new EasyClassA().getClass();//3.通过Class方法的forName方法获取clazz=Class.forName("com.easy725.EasyColor");System.out.println(clazz);//类的类对象中存储了类中定义的内容,属性/方法/构造方法。}
}

获取和设置属性值:Field
getField("name") 可以获取 Easy 类中名为 name 的公共属性,并且可以通过 fName.get(easy) 获取 easy 对象的 name 属性的值。
getDeclaredField("code") 可以获取 Easy 类中名为 code 的任意访问控制修饰符的属性(包括私有属性),但是在访问私有属性前需要调用 setAccessible(true) 设置访问权限。
注意事项:

getField 和 getFields 只能获取公共的字段(即使用 public 修饰的字段),而 getDeclaredField 和 getDeclaredFields 则可以获取类中声明的所有字段,不论其访问控制符是什么。对于私有字段,必须通过 setAccessible(true) 来解除访问限制。

package com.easy726;import java.lang.reflect.Field;
import java.util.HashMap;public class EasyClassB {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {//类的类对象中存储了类中定义的内容(属性/方法/构造方法)。Class c=Easy.class;c=new Easy().getClass();c=Class.forName("com.easy726.Easy");//获取内容//1.获取类中的属性//java中用来记录类的属性的类叫做Filed。//fName指向的对象就是Easy类中的name属性。Field fName=c.getField("name");Easy easy=new Easy();easy.name="张三";System.out.println(easy.name);//可以获取某一个Easy类的对象的name属性的值Object objectName=fName.get(easy);System.out.println(objectName+"---");//注入该属性的值fName.set(easy,"李四");System.out.println(easy.name);//getField和getFields只能获取类中的public声明的属性Field fCode=c.getDeclaredField("code");fCode.set(easy,"10001");//设置code属性的值Object objCode=fCode.get(easy);//通过反射获取easy对象的code属性的值System.out.println(objCode);Field fSex=c.getDeclaredField("sex");Field fAddress=c.getDeclaredField("address");fSex.set(easy,"女");//反射访问私有属性,必须先获取访问权限。fAddress.setAccessible(true);fAddress.set(easy,"青岛");System.out.println(fAddress.get(easy));//getFields()}
}

getInstance 方法:

getInstance 方法利用反射创建一个指定类的对象,并根据传入的 values 参数设置对象的属性值。
Class.newInstance() 方法通过调用目标类的无参构造方法来实例化对象。
设置属性访问权限:
破坏类的封装性:

反射可以访问和修改类中私有的字段,这可能会破坏类的封装性,因为它允许绕过类的设计意图直接访问私有数据成员。

package com.easy726;import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;public class EasyClassC {//反射:在程序运行期间,可以动态获取类中定义的属性和方法以及构造方法的机制(思想)的实现//反射的核心是Class类,程序中使用的类,每一个都有一个唯一对应的Class对象//反射的API:Field,Method,Constructor//反射会破坏类的封装性,通过场景说明public static <T> T getInstance(Class<T> tClass, Map values) throws IllegalAccessException, InstantiationException {//通过反射来获取实例,创建对象T t=tClass.newInstance();//通过类中的无参构造方法,创建对象。//通过反射获取类中定义的属性Field[] farr=tClass.getDeclaredFields();//System.out.println(Arrays.toString(farr));for (Field fitem:farr){//获取属性的名字String fname=fitem.getName();//获取属性的名字//获取该属性在Map中的键值对(属性对应的值)Object value=values.get(fname);//设置属性访问权限fitem.setAccessible(true);fitem.set(t,value);}return t;}public static void main(String[] args) throws InstantiationException, IllegalAccessException {Map map=new HashMap<>();map.put("code","C10001");map.put("name","张三");map.put("esx","女");Student stu=getInstance(Student.class,map);System.out.println(stu);}
}
class Student{private String code;private String name;private String sex;@Overridepublic String toString() {return "Student{" +"code='" + code + '\'' +", name='" + name + '\'' +", sex='" + sex + '\'' +'}';}
}

获取方法对象:Method

Method ma = c.getMethod("methodA"); 使用 getMethod() 方法获取了 Easy 类中的名为"methodA" 的公共方法对象 ma。这里 "methodA" 是方法的名称,没有参数。
调用方法:

ma.invoke(easy); 通过 invoke() 方法调用了 easy 对象的 methodA() 方法。invoke() 方法允许在运行时动态地调用方法,即使不知道方法的具体名称和参数。
获取带参数的方法:

Method mb = c.getMethod("methodB", int.class, int.class); 使用 getMethod() 方法获取了 Easy 类中的名为 "methodB",且接受两个 int 类型参数的方法对象 mb。
调用带参数的方法:

mb.invoke(easy, 23, 45); 通过 invoke() 方法调用了 easy 对象的 methodB(int a, int b) 方法,传入了参数 23 和 45。这里的 mb 是 Method 对象,它可以动态调用 easy 对象的方法并传递参数。

package com.easy726;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class EasyClassD {public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {//获取类对象Class<Easy> c=Easy.class;//反射获取方法 MethodEasy easy=c.newInstance();//获取public方法Method ma=c.getMethod("methodA");//调用方法//对象.方法名()   面向对象//method.invoke(对象)    反射的写法ma.invoke(easy);Method mb=c.getMethod("methodB", int.class, int.class);mb.invoke(easy,23,45);}
}

获取构造方法:Constructor

Class<Easy> c = Easy.class;Constructor<Easy> con = c.getConstructor(String.class);
通过 Class 对象获取类的构造方法,然后利用构造方法对象创建类的实例。

实例化对象:
con.newInstance("张三");使用获取到的构造方法对象调用 newInstance 方法来创建类的实例。

修饰符:使用Modifier的方法判断方法/属性/构造方法的修饰符。

获取属性的修饰符:
Field f = c.getDeclaredField("test");int fmod = f.getModifiers();
Boolean bool = Modifier.isStatic(fmod);
通过 Field 对象获取属性的修饰符,然后使用 Modifier.isStatic 方法判断属性是否为静态。
内省:
内省是一种通过反射来获取类的属性、方法等信息,但不会破坏类的封装性,主要用于获取和设置属性的读写方法。

获取属性的读写方法:
使用 Introspector.getBeanInfo 方法获取类的 BeanInfo,然后通过 PropertyDescriptor 获取属性的读写方法。

调用属性的setter方法:
Easy easy = c.newInstance();write.invoke(easy, "zhangsan");
使用反射调用 setter 方法设置属性的值。

package com.easy726;import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.*;
import java.util.Arrays;public class EasyClassE {public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException, IntrospectionException {//反射获取构造方法Class<Easy> c=Easy.class;c.newInstance();//调用无参构造方法Constructor<Easy> con=c.getConstructor();//获取无参构造方法con.newInstance();con=c.getConstructor(String.class);con.newInstance("张三");//修饰符,使用Modifier的方法判断方法/属性/构造方法的修饰符Field f=c.getDeclaredField("test");int fmod=f.getModifiers();Boolean bool=Modifier.isStatic(fmod);System.out.println(bool);//内省,也是通过反射来实现的,但是内省不会破坏封装性。//内省获取属性的读方法和写方法来获取和设置属性的内容,不会破坏类的封装性。//获取BeanInfoBeanInfo bi=Introspector.getBeanInfo(c);//获取属性的写的方法和读的方法(setter和getter)PropertyDescriptor[] pds=bi.getPropertyDescriptors();System.out.println(Arrays.toString(pds));String pName=pds[0].getName();//获取属性名字System.out.println("属性名是:"+pName);Method read=pds[0].getReadMethod();//对应属性的getter方法Method write=pds[0].getWriteMethod();//对应属性的setter方法//obj.setName("zhangsan");//面向对象//write.invoke(obj,"zhangsan");//反射Easy easy=c.newInstance();write.invoke(easy,"zhangsan");}
}

html常用标签   简单的css样式

文档类型声明
<!DOCTYPE html>定义了HTML文档类型,告诉浏览器这是一个HTML5文档。
HTML结构
<html>: HTML文档的根元素。
<head>: 包含了文档的元数据,如字符编码声明、标题和样式表。
<meta charset="utf-8">: 声明文档使用UTF-8字符编码,确保中文等非ASCII字符能正常显示。
<title>: 定义文档标题,显示在浏览器的标签页标题栏中。
<style>: 内部样式表,定义了表格和表格单元格的样式。
标题和段落
<h1>, <h2>: 定义标题,1级和2级标题。
<p>: 定义段落,包含文本内容。
图片和超链接
<img>: 插入图片,src属性指定图片路径,alt属性定义图片加载失败时的替代文本。
<a>: 创建超链接,href属性指定链接目标。
表格
<table>: 创建表格。
<tr>: 表格行。
<td>: 表格数据单元格。
colspan(合并列)和rowspan(合并行): 合并单元格。
列表
<ol>: 有序列表。
<ul>: 无序列表。
<li>: 列表项。

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>页面标题</title><style>table,td{border:1px solid deeppink;border-collapse: collapse;}td{width: 70px;text-align: center;padding: 10px;}</style></head><body><!--标题  h1-h6 --><h1>凉州词</h1><h2>凉州词</h2><!--段落--><p>葡萄美酒夜光杯,欲饮琵琶马上催。</p><!--图片--><!-- .代表当前路径   ..代表上一级路径--><img src="./image/easyimg.png" alt="加载失败" /><!-- 超链接--><a href="https://www.baidu.com">链接到百度</a><a href="easy.html"><img src="./image/easyimg.png" alt="加载失败" /></a><table><tr><td>编号</td><td>姓名</td><td>成绩</td></tr><tr><td>1001</td><td>张三</td><td>100</td></tr></table><table><tr><td>1-1</td><td colspan="2">1-2</td><!-- <td>1-3</td> --><td>1-4</td></tr><tr><td rowspan="2">2-1</td><td>2-2</td><td>2-3</td><td>2-4</td></tr><tr><!-- <td>3-1</td> --><td>3-2</td><td rowspan="2" colspan="2">3-3</td><!-- <td>3-4</td> --></tr><tr><td>4-1</td><td>4-2</td><!-- <td>4-3</td><td>4-4</td> --></tr></table><!-- 列表 --><!-- 有序列表(ol)和无序列表(ul)(有无序号) --><ol><li>苹果</li><li>香蕉</li><li>橘子</li></ol><ul><li>苹果</li><li>香蕉</li><li>橘子</li></ul></body>
</html>

表单基础:

<form> 标签定义了一个表单,用于收集用户输入的数据,action 属性指定了表单提交的地址,method 属性指定了提交方式,可以是 get 或 post。
文本输入框:

<input type="text" name="username"/> 定义了一个文本输入框,用于用户输入用户名。
密码输入框:

<input type="password" name="userpassword"/> 定义了一个密码输入框,输入的内容会被隐藏显示。
隐藏域:

<input type="hidden" value="10001" name="id"/> 定义了一个隐藏域,用于存储不希望用户看到或修改的数据,如记录用户ID等。
只读文本框:

<input type="text" readonly value="202111050441" name="code"/> 定义了一个只读文本框,用户不能编辑其内容,仅用于显示。
单选框:

<input type="radio" value="Man" name="sex" id="sexman"/><label for="sexman">男</label> 定义了两个单选框,分别用于选择性别,通过 name 属性实现单选的互斥选择。
复选框:

<input type="checkbox" name="hobby" id="sing" value="sing"/><label for="sing">唱</label> 定义了多个复选框,用户可以选择一个或多个选项,通过 name 属性实现多选。
下拉框:

<select name="province" id="province"> 定义了一个下拉框,用户可以从预定义的选项中选择一个省份。
文本域:

<textarea name="description" id="description" cols="30" rows="10"></textarea> 定义了一个多行文本输入框,用户可以输入多行文本。
按钮:

<button type="submit">提交按钮</button> 是一个提交按钮,用户点击后会提交表单数据。
<button type="button">普通按钮</button> 是一个普通的按钮,不会触发表单提交。
<button type="reset">重置按钮</button> 是一个重置按钮,点击后会将表单中的内容重置为初始状态。
普通按钮(使用 input 标签):

<input type="button" value="普通按钮input"/> 也是一个普通的按钮,类似于上面的 <button> 元素,但使用了 <input> 标签。

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title></head><body><form action="提交表单的地址" method="提交方式get/post"><!-- 表单中的组件 --><input type="text" name="username"/><!-- 密码框 --><input type="password" name="userpassword"/><!-- 隐藏域 --><input type="hidden" value="10001" name="id"/><!-- 单选框 --><!-- readonly只读 --><input type="text" readonly value="202111050441" name="code"/><!-- checked默认选中(互斥可覆盖) --><div><input checked type="radio" value="Man" name="sex" id="sexman"/><label for="sexman">男</label><input type="radio" value="Woman" name="sex" id="sexwoman"/><label for="sexwoman">女</label></div><!-- 复选框 --><!-- disable无法选中 --><div><input type="checkbox" name="hobby" id="sing" value="sing"/><label for="sing">唱</label><input disabled type="checkbox" name="hobby" id="dance" value="dance"/><label for="dance">跳</label><input type="checkbox" name="hobby" id="rap" value="rap"/><label for="rap">rap</label></div><!-- 下拉框 --><!-- selected默认选中 --><div><label for="province">省份</label><select name="province" id="province"><option value="sds">山东省</option><option value="ahs">安徽省</option><option value="xj" selected>新疆</option><option value="sxs">陕西省</option><option value="yns">云南省</option></select></div><!-- 多行输入框(文本域) 两个标签中的内容就是他的值 注意不要回车--><div><textarea name="" id="" cols="30" rows="10"></textarea></div><button type="submit">提交按钮</button><button type="button">普通按钮</button><button type="reset">重置按钮</button><input type="button" value="普通按钮input"/></form></body>
</html>

内部样式:
CSS样式定义了几种选择器:
#boxA: ID选择器,应用于id为boxA的元素,设置了宽度、高度、背景颜色、字体颜色等样式。
div: 标签选择器,应用于所有<div>元素,设置了宽度和高度。
.bgred: 类选择器,应用于所有类名为bgred的元素,设置了背景颜色为红色并隐藏(display: none;)。
内联样式和元素:
内联样式:直接在元素上使用style属性设置样式,例如第一个<div>的样式设置了宽度、高度和背景颜色。
ID选择器应用:第二个<div>使用了ID选择器#boxA,应用了预定义的样式。
类选择器应用:后面两个<div>使用了类选择器.bgred,共享类样式,设置了背景颜色为红色并隐藏。

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title><style>/* 内部样式 *//* 选择器 *//* ID选择器 */#boxA{width: 100px;height: 100px;background-color: black;/* 字体颜色 */color: aqua;/* 文本大小 */font-size: 20px;text-align: center;/* 单行文本垂直居中 行高等于容器的高度 */line-height:100px;/* 字体加粗 */font-weight: bold;}/* 标签选择器(元素选择器) */div{width: 100px;height: 100px;}/* 类选择器  class='bgred'*/.bgred{background-color: red;display: none;}</style></head><body><!-- 内联样式 --><div style="width: 100px;height: 100px;background-color:peru"></div><div id="boxA">Hellow</div><div class="bgred"></div><div class="bgred"></div></body>
</html>

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 研究生选择学习Android开发的利与弊?
  • 短视频矩阵系统搭建教程,源码获取,部署上线指南
  • Windows - C 语言开发环境 llvm-mingw + vscode (零基础超适用)
  • MySQL存储
  • 【进阶篇-Day13:JAVA中IO流之字节缓冲流的介绍】
  • Redis缓存穿透、击穿和雪崩的理解和解决思路
  • 如何有效管理众多账号密码:选择适合你的密码管理工具
  • kafka架构+原理+源码
  • PHP $_POST 变量
  • 全链路追踪 性能监控,GO 应用可观测全面升级
  • Python数值计算(9)
  • 大数据-54 Kafka 安装配置 环境变量配置 启动服务 Ubuntu配置 ZooKeeper
  • 【iOS】—— iOS持久化
  • 【Git】.gitignore全局配置与忽略匹配规则详解
  • 快速识别音频文件转成文字
  • 收藏网友的 源程序下载网
  • [数据结构]链表的实现在PHP中
  • 07.Android之多媒体问题
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • Gradle 5.0 正式版发布
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • Map集合、散列表、红黑树介绍
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • SegmentFault 2015 Top Rank
  • swift基础之_对象 实例方法 对象方法。
  • tweak 支持第三方库
  • 飞驰在Mesos的涡轮引擎上
  • 前端临床手札——文件上传
  • 前嗅ForeSpider教程:创建模板
  • 手写双向链表LinkedList的几个常用功能
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 用Visual Studio开发以太坊智能合约
  • 优秀架构师必须掌握的架构思维
  • 自动记录MySQL慢查询快照脚本
  • 阿里云API、SDK和CLI应用实践方案
  • 支付宝花15年解决的这个问题,顶得上做出十个支付宝 ...
  • #162 (Div. 2)
  • #define用法
  • #HarmonyOS:Web组件的使用
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (七)Appdesigner-初步入门及常用组件的使用方法说明
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (一)、python程序--模拟电脑鼠走迷宫
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)Windows2003安全设置/维护
  • *p=a是把a的值赋给p,p=a是把a的地址赋给p。
  • *算法训练(leetcode)第四十五天 | 101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题、104. 建造最大岛屿
  • .dat文件写入byte类型数组_用Python从Abaqus导出txt、dat数据
  • .net wcf memory gates checking failed
  • .net6使用Sejil可视化日志
  • .net和php怎么连接,php和apache之间如何连接