124java

13 阅读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;

 

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

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");
        
        // 获取所有public字段(包括继承的)
        Field[] fields = cls.getFields();
        for (int x = 0; x < fields.length; x++) {
            System.out.println(fields[x]);
        }
        
        // 如果需要获取所有声明的字段(包括private,但不包括继承的)
        Field[] declaredFields = cls.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println("声明的字段: " + field);
        }
    }
}

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

 

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

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

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

范例:通过反射操作属性

package cn.mldn.demo;

import java.lang.reflect.Field;

class Person {
    private String name; // 将属性设为private更符合封装原则
}

public class TestDemo {
    public static void main(String[] args) throws Exception {
        // 1. 修正类路径(去除空格)
        Class<?> cls = Class.forName("cn.mldn.demo.Person");
        
        // 2. 使用Class的getDeclaredConstructor().newInstance()替代已过时的newInstance()
        Object obj = cls.getDeclaredConstructor().newInstance();
        
        // 3. 获取name字段(区分大小写)
        Field nameField = cls.getDeclaredField("name");
        
        // 4. 取消访问检查(针对private字段)
        nameField.setAccessible(true);
        
        // 5. 设置字段值
        nameField.set(obj, "张三");
        
        // 6. 获取字段值并打印
        System.out.println(nameField.get(obj));
    }
}

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

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

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

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

package cn.mldn.demo;

import java.lang.reflect.Field;

class Person {
    private String name; // 修正字段类型大小写和类结构
}

public class TestDemo {
    public static void main(String[] args) throws Exception {
        // 修正类路径分隔符和空格
        Class<?> cls = Class.forName("cn.mldn.demo.Person");
        
        // 修正对象创建方式(使用构造器)
        Object obj = cls.getDeclaredConstructor().newInstance();
        
        // 修正Field类名拼写
        Field nameField = cls.getDeclaredField("name");
        
        // 设置可访问性(私有字段需要)
        nameField.setAccessible(true);
        
        // 输出字段类型信息
        System.out.println(nameField.getType().getName());      // 输出: java.lang.String
        System.out.println(nameField.getType().getSimpleName()); // 输出: String
    }
}

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