反射
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;
@Override
public 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;
//反射获取方法 Method
Easy 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);
//内省,也是通过反射来实现的,但是内省不会破坏封装性。
//内省获取属性的读方法和写方法来获取和设置属性的内容,不会破坏类的封装性。
//获取BeanInfo
BeanInfo 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>