123java

263 阅读3分钟

Java高级开发

在之前已经成功实现了类的构造调用、方法调用,除了这两种模式外还需要有成员调用。

 

前提:

类中的所有属性定要在类对象实例化之后才会进行空间的分配,此时如果想调用类的属性,必须保证实例化对象,而通过反射的newInstance()方法可以直接取得实例化对象(Object类型)

 

在Class类里面提供有两组取得属性的操作方法:

·取得父类属性:

|-取得类中的全部属性:

public Field[] getFields) throws SecurityException;

 

|-取得类中指定名称的属性:

public Field getF ield(String name )throws NoSuchFiel dExcept ion, Securi tyException

 

·取得本类属性:

|-取得类中的全部属性:public Field[] getDeclaredFields () throws Securi tyException

 

|-取得类中指定名称的属性:

public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException;

 

范例:取得类中的全部属性

package cn.mldn.demo;

import java.lang.reflect.Field;

class Person {
    public String name; // 父类中的公共字段
}

class Student extends Person {
    private String school; // 子类中的私有字段
}

public class TestDemo {
    public static void main(String[] args) throws Exception {
        Class<?> cls = Class.forName("cn.mldn.demo.Student");
        
        // 获取所有公共字段(包括从父类继承的)
        Field[] fieldArray = cls.getFields();
        
        // 遍历并打印所有公共字段
        for (int x = 0; x < fieldArray.length; x++) {
            System.out.println(fieldArray[x]);
        }
    }
}

在实际的开发之中,属性基本上都会进行封装处理,所以没有必要关注父类中的属性,也就是说以后的操作所取得的属性都以本类属性为主。

 

  • 属性的核心描述类的方法及范例

现在就需要关注属性的核心描述类:

java.lang. reflect.Field,在这个类里面有两个重要的方法:

 

设置属性内容:

public void set (0bject obj,0bjectvalue)throws IllegalArgumentExcept ion,llegalAccessException

·取得属性内容:public 0bject get (0bject obj)throws IllegalAr gumentException, IllegalAccessException

在AccessibleObject类之中提供有一个方法:

·动态设置封装:public 0bject get (0bject obj)throws IllegalAr gumentException, IllegalAccessException

范例:通过反射操作属性

public class TestDemo {
    public static void main(String[] args) {
        try {
            // 1. 修正类名,移除空格
            Class<?> cls = Class.forName("cn.mldn.demo.Person");
            
            // 2. 使用Constructor.newInstance()替代过时方法
            // 3. 修正Object类名大小写
            Object obj = cls.getDeclaredConstructor().newInstance();
            
            // 反射操作字段
            Field nameField = cls.getDeclaredField("name");
            nameField.setAccessible(true);
            nameField.set(obj, "张三");
            System.out.println(nameField.get(obj));
            
        } catch (ClassNotFoundException | NoSuchFieldException | 
                 InstantiationException | IllegalAccessException | 
                 InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

如果在实际开发中使用更多的属性操作绝对不可能直接按照如上的模式进行,一定要使用setter、getter方法,因为可以给用户操作的机会。

三、Filed里面一个特别有用的方法

在Field类里面有一个特别有用的方法:

取得属性类型:publ ic Class<?> getType )

package cn. mldn. demo;·

import iava. lang. cfect.fild-

 

class Person .

 

1· private string name ;//此时的类中只是明确的提供在个屈性。 public class_ TestDemo f.

public static void main(String[ 1 args) throws Exception f Class<?> cls = Class . forName( "cn. mldn : demo.Person") ir Object obj _ = c1s.newInstance( )//实例化本类对象

Feld nameField = cls. getDeclaredField( "name") ; 11 #ftname System . out . println( nameField. getType() . getName()); 11 t.# Sys tem . out . println( nameField. getType() . getSimpleName());11

将Field 取属性与Method类中的invoke()结合在一起,就可以编写非常灵活的程序了