1. 反射
https://blog.csdn.net/codejas/article/details/78635926
1.1 概念
在运行状态中,任意一个类都能获得这个类的所有方法和属性,对于任意一个对象都能够调用它的任意属性和方法,这种运行时获得信息和动态调节对象的方法为反射。
getClass()
返回当前实例的
Class
对象
Class
类和java.lang.reflect
类库一起完成反射的支持,类库中包含Field
,Method
,Constructor
类。
public class reflectt {
public static void main(String[] args) {
Test test = new Test();
Class testClass = test.getClass();
System.out.println(testClass.getName());// 获得类的完整名(包含包信息)
System.out.println(testClass.getSimpleName());// 获得底层类名(不含包信息)
System.out.println(testClass.getFields());// 获得字段数组
System.out.println(testClass.getMethods());// 获得方法数组
System.out.println(testClass.getConstructors());// 获得构造器数组
}
}
class Test{
public static int count = 0;
final String TAG = "test";
public String getName01() {
return this.TAG;
}
private String getName02() {
return this.TAG;
}
String getName03() {
return this.TAG;
}
protected String getName04() {
return this.TAG;
}
}
1.2 获得Class的方法
三种方法:
- 对象调用
getClass()
,eg:object.getClass()
- 类本身的静态字段
.class
,eg:myClass.class
- 给出类的字符串就可以获得该类的
Class
对象,eg:Class.forName("myClass")
- 该方法需要处理异常
1.3 通过反射获得信息
- 构造器
Construct
可以创建对象,字段Field
可以修改和获得对象的属性(包括私有属性),方法Method
可以调用
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class reflectt {
public static void main(String[] args) {
try {
Class testClass = Class.forName("Test");
System.out.println(testClass.getName());// 获得类的完整名(包含包信息)
System.out.println(testClass.getSimpleName());// 获得底层类名(不含包信息)
System.out.println(testClass.getFields());// 获得字段数组
System.out.println(testClass.getMethods());// 获得方法数组
System.out.println(testClass.getConstructors());// 获得构造器数组
// 获得和使用构造器
Constructor<Test> constructNull = \testClass.getConstructor();// 获得无参数构造器
Constructor<Test> constructorStr = testClass.getConstructor(String.class);// 获得参数为String的构造器
Test objNull = constructNull.newInstance();
Test objStr = constructorStr.newInstance("hello");// 直接使用Class可以构造对象
// 获得和修改属性
Field field = testClass.getField("t");// 只能获得public修饰的属性
System.out.println(field.toString());// 返回类型和位置
System.out.println(field.canAccess(new Test()));// 判断能够访问
Field field2 = testClass.getDeclaredField("pri");// 获得所有声明的属性
field2.setAccessible(true);// 使私有属性可访问
field2.setInt(objNull, 2); // 可以破坏封装,修改私有属性
System.out.println((int)field2.getInt(objNull));
// 获得和调用方法
Method m1 = testClass.getMethod("getName01", null);// 只能获得public方法
System.out.println(m1.invoke(objNull, null));
Method m2 = testClass.getMethod("getName01", String.class);
System.out.println(m2.invoke(objNull, "hello"));
//Method m3 = testClass.getDeclaredMethod(arg0, arg1); 获得所有方法
}catch(Exception e) {
e.printStackTrace();
}
}
}
class Test{
public static int count = 0;
final String TAG = "test";
public String t = "ss";
private int pri = 1;
public Test() {
}
public Test(String s) {
}
public String getName01() {
return this.TAG;
}
public String getName01(String s) {
return s+this.TAG;
}
private String getName02() {
return this.TAG;
}
String getName03() {
return this.TAG;
}
protected String getName04() {
return this.TAG;
}
}
android开发中的资源实例的创建就是利用反射方法的工厂模式,通过
findViewById
指定确定的资源id来获得要创建实例的类型和属性,并返回创建完成的实例,实现分离。
2. 静态块
静态块指的是static{}
代码块,仅在类加载时有且仅执行一次,例如类实例化就执行,且无论实例化多少都仅在第一次实例化时执行一次。
import java.lang.reflect.Constructor;
public class Main {
static {
System.out.println("hello world");
};
public static void main(String[] args) throws Exception {
Constructor constor = Main.class.getConstructor();
Main m1 = (Main)constor.newInstance();
Main m2 = (Main)constor.newInstance();
}
}
-
类加载的含义
-
Class.forName
显式加载时- 也可以自己设定此时不加载类
- 实例化
- 调用类的静态
static
方法 - 调用类的静态
static
变量- 但调用类的静态常量
static final
不会加载类
- 但调用类的静态常量
-
- 静态块代码按照顺序先后执行
- 先执行完
static
块语句才执行调用的方法
public class TestStatic{
static{
System.out.println(1);
}
static {
System.out.println(2);
}
static {
System.out.println(3);
}
public static void main(String args[]){
System.out.println(5);
}
static {
System.out.println(4);
}
}
// 输出12345
————————————————
版权声明:本文为CSDN博主「lubiaopan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lubiaopan/java/article/details/4802430
3. 泛型
面向对象类型安全的一种机制:
- 创建泛化实例
ArrayList<int> a = new ArrayList<int>();
// 之前也说过之前的java不支持int作为泛型,因为它不是类,但后来引入自动封装和解包机制
- 声明和指定泛化类型的变量
- 函数参数泛型声明
// 常用方法是类上声明泛型(接口也有泛型)
public class ArrayList<E> extends AbstractList<E>...{
public boolean add(E o){// 在类上定义的泛型可以在类中其他位置当作类型直接使用
// ...
}
}
// 不常用的方法,如果未定义在类声明的类型,需要对方法泛型
public <T extends Animal> void takeThings(ArrayList<T> a){
// 这里的意思是T可以是任意一种Animal,即自身及其子类
// ...
}
上面的形式不同于
public void takeThings(ArrayList<Animal> a)
,上面形式指Animal
及其子类可以作为参数,但是这里提到的方法仅支持Animal
类型
- 如果可以指定类的泛化,也就可能支持接口的泛化
public static <T extends Iterface> void quip(List<T> list){
// ...
}
如果接口也是泛化接口时:
public static <T extends Comparable<? super T>> void sort(List<T> list){
// ...
}