一、反射
1.定义:
反射(Reflection)是一种强大的机制,在程序运行期间,可以动态获取类中定义的属性和方法以及构造方法的机制(思想)的实现。
反射的核心是Class类 程序中使用的类,每一个都有一个唯一对应的Class对象
反射的API:Field Method Constructor
反射会破坏类的封装性 通过场景说明
(1)在java中存储了类的内容,这个内容也应该是一个对象
(2)java中每一个类都有一个内存,每一块内存都是一个对象
(3)这些对象记录了这些类中声明了那些属性和方法以及构造方法
(4)java将这类抽象为一个Class类
2.获取类的类对象
Class类的对象是不能new的
(1)通过类名获取类对象
Class clazz= EasyClassA.class;
(2)通过对象来获取:类对象
clazz =new EasyClassA().getClass();
(3)通过Class方法的forName方法获取
clazz=Class.forName("com.easy725.Easy");
类的类对象中存储了类中定义的内容 属性、方法、构造方法
3.获取类中的属性
(1)java中用来记录类的属性的类 叫做Field
Field fName= c.getField("name");
fName变量指向的对象是Easy类中的name属性
新建一个Easy类的实例,然后定义easy对象的name属性为“张三”,声明一个Object类的对象来接收Easy类的对象的name属性值,代码如下:
Easy easy=new Easy();
easy.name="张三";
System.out.println(easy.name);
//可以获取某一个Easy类的对象的name属性的值
Object objectName=fName.get(easy);
System.out.println(objectName+"------");
(2)注入该属性的值set(类,属性名)
fName.set(easy,"李四");System.out.println(easy.name);
getField getFields 只能获取类中public声明的属性
反射访问受保护的属性时需要使用getDeclaredField(属性名);
Field fCode=c.getDeclaredField("code");
反射访问私有属性,必须先获取访问权限
fAddress.setAccessible(true); fAddress.set(easy,"青岛"); System.out.println(fAddress.get(easy));
getFields() 获取所有属性
下面是Easy类的声明:
package com.easy726;
public class Easy {
public String name;
protected String code;
String sex;
private String address;
static int maxage;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public static int getMaxage() {
return maxage;
}
public static void setMaxage(int maxage) {
Easy.maxage = maxage;
}
public static final transient String test=null;
public Easy(){
}
public Easy(String name){
this.name=name;
}
public void methodA(){
System.out.println("methodA");
}
public void methodB(int a,int b){
System.out.println("methodB");
System.out.println("两个参数分别为"+a+","+b);
}
}
反射的示例:
首先定义一个Student类,里面定义了code、name和sex属性,还有重写的toString方法。在测试方法中,使用泛型来确保参数和返回值类型是Class类,参数是Class类和Map类型的对象,首先创建对象通过反射类获取类中定义的属性,然后将属性名作为key,来查找Map中对应的value值,设置一个Object类对象来存储键值对,设置访问权限,将键值对注入新建的对象实例。主函数设置了Map类中的键值对。
package com.easy726;
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 InstantiationException, IllegalAccessException {
//通过反射获取实列 创建对象
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","C1001");
map.put("name","宣行琮");
map.put("sex","男");
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 + '\'' +
'}';
}
}
4.获取类中的方法 Method
Method ma=c.getMethod("methodA");无参
调用该方法 method.invoke(对象)
ma.invoke(easy);
Method mb=c.getMethod("methodB",int.class,int.class); mb.invoke(easy,23,45);有参
类对象都是前面的Easy类。
5.获取构造方法Constructor
获取无参的构造方法
Constructor<Easy> con= c.getConstructor();
获取有参的构造方法
con=c.getConstructor(String.class);
创建一个实例并将name属性设置为宣行琮
con.newInstance("宣行琮");有参的构造方法
6.修饰符
使用modifier的方法判断方法、属性、构造方法的修饰符
Field f=c.getDeclaredField("test"); int fmod=f.getModifiers(); boolean bool=Modifier.isStatic(fmod); System.out.println(bool);判断是否使用static修饰
二、内省
也是通过反射来实现的 不会破坏封装性
(1)获取BeanInfo
BeanInfo bi= Introspector.getBeanInfo(c);
(2)获取属性的写的方法和读的方法 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方法
(3)使用写方法
Easy easy=c.newInstance(); write.invoke(easy,"zhangsan");
三、HTML
显示在页面上的内容都要写在标签body内
1.会显示在窗口 标签title
<title>页面标题</title>
2.标题,标签h1--h6
<h1>凉州词</h1>
<h2>凉州词</h2>
3.段落 标签p
<p>葡萄美酒夜光杯,欲饮琵琶马上催</p>
<p>醉卧沙场君莫笑,古来征战几人回</p>
4.图片显示 标签 img
<img src="./image/kui.jpg" alt="失败了"/>
alt中是图片加载失败后,显示的文本
失败的话
5.超链接 标签a
<a href="https://www.baidu.com">连接到百度</a>
<a href="easy1.html"><img src="./image/kui.jpg" alt="失败了"/></a>
点击文字和图片都能跳转,标签a中设置要跳转网页的地址
6.表格 标签table tr行 td列
<table>
<tr>
<td>编号</td>
<td>姓名</td>
<td>成绩</td>
</tr>
<tr>
<td>1001</td>
<td>张三</td>
<td>100</td>
</tr>
</table>
设置出了两行三列的表格
也可以使用colspan和rowspan来合并单元格
colspan合并行,rowspan合并列、
建立一个4*4的表格
<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>
7.列表
(1)有序列表 标签 ol 有序号
<ol>
<li>苹果</li>
<li>香蕉</li>
<li>橘子</li>
</ol>
(2)无序列表 标签 ul 无序号
<ul>
<li>苹果</li>
<li>香蕉</li>
<li>橘子</li>
</ul>
8.表单 form
<form action="提交表单的地址" method="提交的方式get/post">
表单中的组件
(1)输入框input
<input type="text" name="username" value="宣行琮"/>
name在窗口会显示,value值是页面加载后的初始值
(2)密码框 password
将type设为password
<input type="password" name="userpass" />
(3)只读
设置readonly 就不可修改
<input type="text" readonly value="21120501152" name="code"/>
(4)隐藏域hidden
将type设置为hidden,就不会出现在页面上
(5)单选框radio
在一个表单内,name值一样的就会有互斥性
<input checked type="radio" value="M" name="sex" id="sexman"/><label for="sexman">男</label>
<input type="radio" value="W" name="sex" id="sexwoman"/><label for="sexwoman">女</label>
在label标签中设置for,当点到文字时也能选择上
checked 初始化时的选项
(6选框checkbox
display不可选
<div>
<input checked 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>
(7)下拉框 标签select 选项option
<div>
<label for="province">省份</label>
<select name="province" id="province">
<option>山东省</option>
<option value="ahs">安徽省</option>
<option value="xj">新疆</option>
<option value="sxs" selected>陕西省</option>
<option value="yns">云南省</option>
</select>
</div>
(8)文本域textarea
多行文本框 两个标签中的内容就是他的值 注意不要回车
<div>
<!-- 文本域 多行文本框 两个标签中的内容就是他的值 注意不要回车-->
<textarea></textarea>
</div>
(9)按钮
<!-- 提交按钮 -->
<button type="submit">提交按钮</button>
<!-- 普通按钮 -->
<button type="button">普通按钮</button>
<!-- 重置按钮 -->
<button type="reset">重置按钮</button>
<input type="button" value="普通按钮Input">
<input type="submit" value="提交按钮Input">
<input type="reset" value="重置按钮Input">
可以使用button也可以使用input
9.样式
在style中设置
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
/*内部样式 */
/* 样式选择器 */
/* ID选择器 */
#boxA{
height: 100px;
width: 100px;
background-color: skyblue;
/* 字体颜色 */
color: green;
font-size: 30px;
text-align: center;
/* 单行文本 垂直居中 行高等于容器的高度*/
line-height: 100px;
font-weight: 600;
/* font-weight: bold;字体加粗 */
}
/* 标签选择器 元素选择器 */
div{
height: 100px;
width: 100px;
}
/* 类选择器 class='bgred'*/
.bgred{
background-color: red;
/* 不显示 */
display: none;
}
</style>
</head>
<body>
<!--内联样式 -->
<div style="width: 100px;height: 100px;background-color: deeppink;"></div>
<div id="boxA">你好</div>
<div class='bgred'></div>
<div class='bgred'></div>
</body>
</html>