zoukankan      html  css  js  c++  java
  • java反射和泛型简介

    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 = 	estClass.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){
        // ...
    }
    
  • 相关阅读:
    mysql高级查询
    RabbitMq应用一的补充(RabbitMQ的应用场景)
    LNMP的并发配置和资源分配
    大神教你Nginx常用基础配置方案
    案例:配置apache和nginx的SSL加密传输协议
    Nginx配置服务器静态文件支持跨域访问
    菜鸟学习计划浅谈之Linux系统
    细述:nginx http内核模块提供的变量和解释
    如何在Linux中使用Firejail运行应用程序
    一款用于对 WiFi 接入点安全进行渗透测试的工具
  • 原文地址:https://www.cnblogs.com/oneflyleader/p/13284282.html
Copyright © 2011-2022 走看看