JAVA开发学习-day11
1. 反射
Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。
1.1 获得类对象(Class)的三种方法
反射可以用于判断任意对象所属的类,获得 Class 对象,构造任意一个对象以及调用一个对象。有对象必须要有类,而每一个类都有一个Class对象,每创建一个新类就创建了一个Class对象,Class类对象就记录了类所声明的变量,构造方法和方法。
获取Class对象有三种方法
- 1.通过类名直接获取
- 2.调用某个对象的getClass方法
- 3.通过Class的forName方法获取
//1.通过类名获取类对象
Class clazz = EasyClassA.class;
//2.调用某个对象的getClass方法获取类对象
clazz = new EasyClassA().getClass();
//3.通过Class方法的forName方法获取
try {
clazz = Class.forName("com.zxst.day11.EasyClassA");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
1.2 获取类的成员变量
获取某个类的成员变量,我们可以使用Class对象的getField方法和getDeclaredField方法,这两个方法的返回值是Field类对象,Field就是类中的成员变量,通过Field,我们可以获取,设置和操作对象的属性值。
- getField():访问公有的成员变量,可以获得父类中公有的成员变量
- getFields(): 获取所有的公有成员变量,包括父类的公有成员变量,返回值为Field数组
- getDeclaredField():访问任意权限的成员变量,但不能访问父类的成员变量
- getDeclaredFields():访问获取所有的成员变量,但不能访问父类的成员变量,返回值为返回值为Field数组
首先创建一个Easy类,和它的父类FatherOfEasy
public class Easy extends FatherOfEasy{
public String name;
protected String code;
String sex;
private String address;
static int maxAge;
public static final transient String test = null;
public Easy(){}
public Easy(String name){
this.name = name;
}
}
class FatherOfEasy{
public String father;
}
获得Easy类对象,通过getField方法和getDeclaredField方法来得到Easy类中的成员变量Field,调用Field的get和set方法来查看和修改成员变量的值
public class EasyClassB {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//获取类对象
Class c = Easy.class;
//获取类中的属性
//java中用来记录 类的属性的类叫做Field
//获取某一个Easy类的对象的name属性的值
Field fName = c.getField("name");
System.out.println(fName);//public java.lang.String com.zxst.day11.Easy.name
Easy easy = new Easy();
easy.name = "张三";
System.out.println(easy.name); //张三
//可以获取某一个Easy类的对象的name属性的值
Object obj = fName.get(easy);
System.out.println(obj + "--------");//张三--------
//修改某个Easy类对象的name
fName.set(easy,"无敌");
obj = fName.get(easy);
System.out.println(obj + "--------");//无敌--------
System.out.println(easy.name);//无敌
//getField可以获取父类声明的成员变量
fName = c.getField("father");
easy.father = "父类的成员变量";
obj = fName.get(easy);
System.out.println(obj); //父类的成员变量
//getDeclaredField不能获取父类声明的成员变量
//fName = c.getDeclaredField("father"); //NoSuchFieldException: father
//getField getFields 只能获取类中的public声明的属性
/*Field fCode = c.getField("code"); //NoSuchFieldException: code
obj = fCode.get(easy);
System.out.println(obj);*/
//getDeclaredField方法可以访问所有已经声明的对象
Field fCode = c.getDeclaredField("code");
fCode.set(easy, "10001");
obj = fCode.get(easy); //通过反射获取easy对象的code属性值
System.out.println(obj);//10001
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));//青岛
System.out.println(fSex.get(easy));//女
}
}
1.3 获取类的方法
可以通过Class对象的getMethod方法和getDeclaredMethod方法来获取类对象的方法
- getMethod(): 获取类的一个公共方法,可以获取父类中公有的方法
- getMethods(): 获取类的所有公共方法,包括父类的公共方法,因此返回值中会包含Object类的方法,返回值为Method数组
- getDeclaredMethod(): 获取类对象的一个方法,也可以获取父类的公共方法
- getDecalredMethods(): 获取一个类对象的所有方法,包括父类的公共方法,但是不包括Object类的公有方法,返回值为Method数组
创建一个Easy类和它的父类
public class Easy extends FatherOfEasy{
public void methodA(){
System.out.println("methodA");
}
private void methodB(int a, int b){
System.out.println("methodB");
System.out.println("两个参数分别为" + a + "," + b);
}
}
class FatherOfEasy{
public void fatherMethod(){
System.out.println("这是父类的方法");
}
}
通过getMethod()和getDeclared()方法来获取类对象的方法,通过invoke对象调用类的方法
public class EasyClassD {
public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
//获取类对象
Class c = Easy.class;
//反射获取方法 Method
Easy easy = (Easy)c.newInstance();
//获取public方法
Method method = c.getMethod("methodA");
//使用Method对象的invoke方法来调用Easy类对象的方法
method.invoke(easy); //methodA
//获取父类方法
method = c.getMethod("fatherMethod");
method.invoke(easy);//这是父类的方法
//getDeclaredMethod可以获取私有方法
//获取有参数的方法时,需要在后面加上方法参数的Class对象
method = c.getDeclaredMethod("methodB", int.class, int.class);
//调用私有方法需要setAccessible(true)
method.setAccessible(true);
method.invoke(easy,12,34); //两个参数分别为12,34
//getDeclaredMethod也可以获取父类方法
method = c.getDeclaredMethod("fatherMethod");
method.invoke(easy);//这是父类的方法
Method[] methods = c.getDeclaredMethods();
for (Method method1 : methods){
System.out.println(method1);
//输出为methodA,methodB,fatherMethod方法
}
System.out.println();
methods = c.getMethods();
for (Method method1 : methods){
System.out.println(method1);
//输出为methodA,fatherMethod方法和Object类中的公共方法
}
}
}
1.4 获取构造器
可以通过getConstructor方法来获取一个Constructor类的构造器对象,通过这个构造器对象的newInstance(),来创建类的对象
getConstructor(): 返回类的构造器对象
创建一个Easy类对象
public class Easy{
public String name;
protected String code;
String sex;
private String address;
static int maxAge;
public static final transient String test = null;
public Easy(){}
public Easy(String name){
this.name = name;
}
}
获取一个Easy类,调用Class的getConstructor方法来获得Easy类的构造器,在通过构造器对象的newInstance方法来创建Easy对象
public class EasyClassE {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException, IntrospectionException {
//反射获取构造方法
//Constructor
Class<Easy> c = Easy.class;
Easy easy = c.newInstance(); //调用无参构造方法
//获取无参构造方法
Constructor<Easy> constructor = c.getConstructor();
easy = constructor.newInstance();
constructor = c.getConstructor(String.class);
easy = constructor.newInstance("张三");
System.out.println(easy.name);//张三
}
}
1.5 判断修饰符
Filed,Method或Constructor对象可以调用getModifiers方法来获得一个int值,然后通过调用Modifier类的判断修饰符的方法可以知晓类的成员属性,方法或构造方法的修饰符。
//使用Modifier的方法判断方法,属性,构造方法的修饰符
Field f = c.getDeclaredField("test");
int fmod = f.getModifiers();
System.out.println(fmod);
boolean bool = Modifier.isStatic(fmod);
System.out.println(bool);//true
每个修饰符(如public
、private
、protected
等)都被分配了一个唯一的整数值,这些值在Modifier
类中定义为静态常量。每个值都是2的幂次方,这样它们就可以通过位运算(如按位与&
)来单独检查。Modifier
类中的方法使用位运算来检查特定的修饰符是否存在于给定的修饰符标志整数中。具体来说,它们通过将给定的修饰符标志与对应的修饰符常量进行按位与运算,然后检查结果是否为非零。如果结果非零,则表示该修饰符存在。
public class Modifier {
public static boolean isPublic(int mod) {
return (mod & PUBLIC) != 0;
}
public static boolean isPrivate(int mod) {
return (mod & PRIVATE) != 0;
}
public static boolean isProtected(int mod) {
return (mod & PROTECTED) != 0;
}
public static boolean isStatic(int mod) {
return (mod & STATIC) != 0;
}
public static boolean isFinal(int mod) {
return (mod & FINAL) != 0;
}
public static boolean isSynchronized(int mod) {
return (mod & SYNCHRONIZED) != 0;
}
public static boolean isVolatile(int mod) {
return (mod & VOLATILE) != 0;
}
public static boolean isTransient(int mod) {
return (mod & TRANSIENT) != 0;
}
public static boolean isNative(int mod) {
return (mod & NATIVE) != 0;
}
public static boolean isInterface(int mod) {
return (mod & INTERFACE) != 0;
}
public static boolean isAbstract(int mod) {
return (mod & ABSTRACT) != 0;
}
public static boolean isStrict(int mod) {
return (mod & STRICT) != 0;
}
public static final int PUBLIC = 0x00000001;
public static final int PRIVATE = 0x00000002;
public static final int PROTECTED = 0x00000004;
public static final int STATIC = 0x00000008;
public static final int FINAL = 0x00000010;
public static final int SYNCHRONIZED = 0x00000020;
public static final int VOLATILE = 0x00000040;
public static final int TRANSIENT = 0x00000080;
public static final int NATIVE = 0x00000100;
public static final int INTERFACE = 0x00000200;
public static final int ABSTRACT = 0x00000400;
public static final int STRICT = 0x00000800;
}
1.6 内省
因为反射可以获取类的私有属性和方法,这样就破坏了类的封装性,如果我们不想破坏类的封装,可以通过内省实现。
内省:底层是通过反射实现,内省获取属性的读方法和写方法(getter/setter)来获取和设置属性的内容,不会破坏类的封装性
因为内省是通过类的getter和setter方法来实现的,所有类要实现相应的getter和setter方法
内省的实现:
创建Easy类
public class Easy{
public String name;
protected String code;
String sex;
private String address;
static int maxAge;
public static final transient String test = null;
public Easy(){}
public Easy(String name){
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public void setCode(String code) {
this.code = code;
}
public void setSex(String sex) {
this.sex = sex;
}
public static void setMaxAge(int maxAge) {
Easy.maxAge = maxAge;
}
public void setAddress(String address) {
System.out.println("这是address的setter方法");
this.address = address;
}
public String getName() {
return name;
}
public String getCode() {
return code;
}
public String getSex() {
return sex;
}
public String getAddress() {
return address;
}
public static int getMaxAge() {
return maxAge;
}
}
BeanInfo bi = Introspector.getBeanInfo(c);
//获取属性的写方法和读方法 setter/getter
PropertyDescriptor[] propertyDescriptors = bi.getPropertyDescriptors();
System.out.println(Arrays.toString(propertyDescriptors));//第一个属性是address
String pName = propertyDescriptors[0].getName();//获取属性的名字
System.out.println("属性名是:" + pName);//属性名是:address
Method read = propertyDescriptors[0].getReadMethod(); //对应属性的getter方法
Method write = propertyDescriptors[0].getWriteMethod(); //对应该属性setter的方法
//通过getter和setter方法,就不会破坏封装性
easy = c.newInstance();
write.invoke(easy,"123");//这是address的setter方法
System.out.println(read.invoke(easy));//123
反射参考资料:https://www.sczyh30.com/posts/Java/java-reflection-1/
2. HTML CSS
2.1 HTML中的常用标签
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>页面标题</title>
<style>
table,td{
border:1px solid black;
border-collapse: collapse; //边框整合在一起
}
td{
width: 80px;
height: 80px;
text-align: center;
padding: 10px;
}
</style>
</head>
<body>
<!-- 标题 h1~h6 -->
<h1>一级标题</h1>
<h2>二级标题</h2>
<h3>三级标题</h3>
<h4>四级标题</h4>
<h5>五级标题</h5>
<h6>六级标题</h6>
<!-- 段落 p -->
<p>秦时明月汉时关,万里长征人未还</p>
<p>但使龙城飞将在,不教胡马度阴山</p>
<!-- 图片标签 -->
<img src="./img/laocui.jpg" alt="图片加载失败后展示的文本" />
<a href="https://www.baidu.com">百度</a>
<a href="easy.html">
</a>
<table>
<tr>
<td>单元格</td>
<td>编号</td>
<td>姓名</td>
</tr>
<tr>
<td></td>
<td>1001</td>
<td>张三</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>2-1</td>
<td>2-2</td>
<td>2-3</td>
<td>2-4</td>
</tr>
<tr>
<!-- 该单元格大小为2行2列 -->
<td colspan="2", rowspan="2">3-1</td>
<!-- <td>3-2</td> -->
<td>3-3</td>
<td rowspan="2">3-4</td>
</tr>
<tr>
<!-- <td>4-1</td> -->
<!-- <td>4-2</td> -->
<td>4-3</td>
<!-- <td>4-4</td> -->
</tr>
</table>
<!-- 列表 -->
<!-- 有序列表 有序号 -->
<ol>
<li>苹果</li>
<li>🍌</li>
<li>橘子</li>
<li>橙子</li>
</ol>
<!-- 无序列表 无序号 -->
<ul>
<li>苹果</li>
<li>🍌</li>
<li>橘子</li>
<li>橙子</li>
</ul>
</body>
</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="password" />
<!-- 只读 -->
<input type="text" readonly value="123456789"/>
<div>
<!-- 单选框 -->
<!-- name相同的单选框只能选择一个 -->
<input checked type="radio" value="男" name="sex" id="man"/><label for="man">男</label>
<input type="radio" value="女" name="sex" id="woman"/><label for="woman">女</label>
</div>
<!-- 复选框 -->
<div>
<input checked type="checkbox" name="hobby" id="sing" value="sing"/><label for="sing"><label for="sing">唱</label>
<input disabled type="checkbox" name="hobby" id="dance" value="dance"/><label for="dance"><label for="dance">跳</label>
<input type="checkbox" name="hobby" id="rap" value="rap"/><label for="rap"><label for="rap">rap</label>
</div>
<!-- 下拉框 -->
<div>
<label for="province">省份</label>
<select name="province" id="province">
<option value="SDS">山东省</option>
<option value="AHS">安徽省</option>
<option value="XJ">新疆维吾尔自治区</option>
<option value="YNS">云南省</option>
<option value="SXS">陕西省</option>
</select>
</div>
<div>
<!-- 文本域 多行文本框 两个标签中的内容就是它的值 注意不要回车-->
<textarea name="" id="" cols="30" rows="10"></textarea>
</div>
<!-- 隐藏域 -->
<input type="hidden" value="这是一个隐藏域" name="hidden"/>
<!-- 按钮 -->
<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" />
</form>
</body>
</html>
CSS选择器
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
/* 内部样式 */
/* id选择器 */
#boxA{
background-color: black;
/* 字体颜色 */
color: white;
font-size: 30px;
text-align: center;
/* 单行文本垂直居中 行高等于容器的高度*/
line-height: 200px;
font-weight: bold;
}
/* 标签选择器 元素选择器 */
div{
width: 200px;
height: 200px;
}
/* 类选择器 class = 'bgred'*/
.bgred{
background-color: red;
display: none;
}
</style>
</head>
<body>
<!-- 内联样式 -->
<div style="width: 100px;height: 100px;background-color: aliceblue;"></div>
<div id="boxA">你好</div>
<div class="bgred"></div>
</body>
</html>