《Thinking in Java》学习笔记(七)

时间:2023-02-25 11:38:25

1.关于反射还有一些需要补充的

package reflect;

public class HiddenClass {
    public A HiddenA(){
        return new A();
    }
}

class A{
    private final String s = "I am totally safe!";
    
    public String getString(){
        return s;
    }
    
    private void print(){
        System.out.println("call method print() in Class A");
    }
}

  和上面的类不在同一包下,写一个测试类:

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import reflect.*;

public class HiddenClassTest {
    
    public static void main(String[] args) throws Exception{
        //A a = new A();  error: A can not be sloved
        
        HiddenClass hc = new HiddenClass();
        //A a = hc.HiddenA(); error
        Object a = hc.HiddenA();
        
        Method m = Class.forName("reflect.A").getDeclaredMethod("print");
        m.setAccessible(true);
        m.invoke(a);
        
        Field f =  Class.forName("reflect.A").getDeclaredField("s");
        f.setAccessible(true);
        f.set(a, "no you are not safe!");
        m = Class.forName("reflect.A").getDeclaredMethod("getString");
        m.setAccessible(true);
        System.out.println(m.invoke(a));
    }
    
}

  运行结果为:

call method print() in Class A
I am totally safe!

  对上述代码的说明:

  1. 类的默认构造方法的修饰符是和所在类的修饰符一致的,reflect.A类的修饰符是缺省,则reflect.A类的缺省的构造方法也就是缺省的。

   在和reflect.A不同包下面的类,例如HiddenClassTest就无法直接构造reflect.A的实例。和reflect.A在同一个包下面的类是可以直接new出一个新对象的。

      普通类构造方法的修饰符只能是public和缺省,内部类的修饰符可能是private,protected,构造方法的修饰符可以是private和protected。

  2. 利用将构造方法置为缺省修饰符可以避免其他包中的类直接构造、调用类的方法,但是通过反射,不管是上面的情形,还是内部类、匿名内部类的情形,都是可以进行访问的。反射就是后门,能解决一些特定的问题。

  3. 利用反射可以调用private方法,修改private类型的变量的值,但是无法修改final类型变量的值,这一点需要注意。final修饰基本变量和String时,值无法改变,final修饰修饰非基本变量时,只会初始化一次。

  4. 使用stacic和final修饰的基本变量和String被称为常量,值无法改变,使用stacic和final修饰修饰非基本类型时,值是可以改变的。 

 2.Java数组

  Java中多维数组的例子如下:

package array;

import java.util.Arrays;

public class MultiDimensionalArrayTest {

    public static void main(String [ ] args) {
        int [] [] a = new int [3] [];
        int [] [] b = new int [] []{{1,2},{3,4,5},{6,7,8,9}};  //每行中元素个数不同的数组也被称为粗糙数组
        int [] [] c = {{1,2},{3,4,5},{6,7,8,9}};
        int [] [] [] d = new int [3] [] [];
        
        System.out.println(Arrays.deepToString(a));
        System.out.println(Arrays.deepToString(b));
        System.out.println(Arrays.deepToString(c));
    }
    
}

  输出为:

[null, null, null]
[[1, 2], [3, 4, 5], [6, 7, 8, 9]]
[[1, 2], [3, 4, 5], [6, 7, 8, 9]]