java截取字符串中的一部分_java提取字符串中某个字符_java中截取字符串

刚开始学习Java的时候真的很难理解反射到底是个什么东西,有些书籍,哪怕是很经典的书籍都解释的让人感觉懵懵的,网友都说在将来学习框架的时候需要经常应用到反射机制java截取字符串中的一部分,这样一来总让人心里有些不安。

方才偶然又把讲解反射的章节和视频看了一点,觉得能理解一些了,现在决定一鼓作气,边看边写,顺便把一些主要的内容和操作都记载到这里。我想,对于我这么一个笨笨的人来说,学习的最好方法也许就是不断重复,遇到不懂的知识就停下来把以往的重新学一遍,虽然浪费了很多时间,但总有些效果。

我的理解是:所谓反射,就是根据一个已经实例化了的对象来还原类的完整信息,至少对我而言,我认为它带给我的好处是,让我从下往上的又了解了一遍面向对象。

Class类

如果要完成反射,那么必须了解Class类。

实例1:通过对象取得包名和类名

package org.siu;  

class Test {  

}  

public class Demo {  
   public static void main(String[] args) {  
       Test t = new Test();  
       System.out.println(t.getClass());  
       System.out.println(t.getClass().getName());  
   }  
}

编译结果如下,注意包的编译方式即可。

此处的getClass()方法是默认继承自Object类的。

java截取字符串中的一部分_java提取字符串中某个字符_java中截取字符串

在Java中,Object类是所有类的父类,同样,所有类的实例化对象也都是Class类的实例。因此,这样一来就会牵扯到向上转型和向下转型的概念,由于向下转型的不安全因素,在这里泛型也会接踵而来。

实例2:Class类的实例化

由于Class类没有构造方法,所以实例化Class类的方式有点特殊,有三种方式:

class Test {  

}  

public class Demo {  
   public static void main(String[] args) {  
       //方式一:  
       Test t = new Test();  
       Class c1 = t.getClass();  
       System.out.println(c1);  

       //方式二:  
       //为了避免特殊性,这里不用Test类,而用java库中的String类  
       Class c2 = String.class;  
       System.out.println(c2);  

       //方式三:  
       //forName()方法会抛出异常  
       Class c3 = null;  
       try {  
           c3 = Class.forName("Test");  
       } catch (ClassNotFoundException e) {  
           e.printStackTrace();  
       }  
       System.out.println(c3);  
   }  
}

其中,forName()方法需要重点掌握,因为它可以在类不确定的情况下实例化Class,更具灵活性。

java截取字符串中的一部分_java提取字符串中某个字符_java中截取字符串

Class类的应用

Class类中有一个方法叫做newInstance(),它可以用来创建一个Class类对象的新实例。

怎么说呢?Class对象包含的内容就是反射好的那个类,我们要构造那个类的新实例(新对象)。

实例3:Class类的无参构造对象

public class Demo {  
   public static void main(String[] args) {  
       //实例化Class对象,forName()方法会抛异常  
       Class c = null;  
       try {  
           //这里需要完整的包名和类名  
           c = Class.forName("java.lang.String");  
       } catch (ClassNotFoundException e) {  
           e.printStackTrace();  
       }  

       //生成一个字符串的引用  
       String s = null;  
       try {  
           //将构造好的对象向下转型为String类  
           //newInstance()方法会抛异常  
           s = (String) c.newInstance();  
       } catch (InstantiationException e) {  
           e.printStackTrace();  
       } catch (IllegalAccessException e) {  
           e.printStackTrace();  
       }  
       System.out.println("字符串长度: " + s.length());  
   }  
}

这样就通过无参数的形式构造了一个新的对象,如同正常模式中。通过无参构造方法来构造新对象一样。

java提取字符串中某个字符_java中截取字符串_java截取字符串中的一部分

我们知道,类中除了有无参构造方法,还会存在有参数的构造方法

那在反射中如何通过有参数的形式构造对象呢?

实例4:Class类的有参构造对象

import java.lang.reflect.Constructor;  

public class Demo {  
   //下面的几个方法抛出来的异常太多,为了代码的紧凑性,这里就直接抛给虚拟机了  
   public static void main(String[] args) throws Exception {  
       Class c = null;  
       try {  
           c = Class.forName("java.lang.String");  
       } catch (ClassNotFoundException e) {  
           e.printStackTrace();  
       }  
       char[] ch = {'h','e','l','l','o'};  
       String s = null;  
       //获得Class类对象的有参构造方法,括号里面参数的写法是:类型.class  
       Constructor con = c.getConstructor(char[].class);  
       //用此构造方法构造一个新的字符串对象,参数为一个char数组  
       s = (String) con.newInstance(ch);  
       System.out.println("构造的字符串:" + s);  
   }  
}

我们还是使用String类做例,因为String类用的比较多,便于理解,这里需要注意的是,构造方法需要使用getConstructor()方法获得。

至于参数类型则是:原有类型.class。

java中截取字符串_java提取字符串中某个字符_java截取字符串中的一部分

还有一点,无论是有参还是无参,这里所使用的构造方法,原本的类里面必须对应存在。那么,如何才能知道原有类里面的构造方法java截取字符串中的一部分,普通方法,继承的父类等详细信息呢?

获取类的结构

要通过反射获取类的结构我们这里要导入一个新的包Java.Lang.Reflect。

实例5:取得类的构造方法

import java.lang.reflect.Constructor;  
import java.util.Arrays;  

public class Demo {  
   //下面的几个方法抛出来的异常太多,为了代码的紧凑性,这里就直接抛给虚拟机了  
   public static void main(String[] args) throws Exception {  
       Class c = null;  
       try {  
           c = Class.forName("java.lang.Boolean");  
       } catch (ClassNotFoundException e) {  
           e.printStackTrace();  
       }  
       //这里的getConstructors()方法返回的是一个Constructor数组  
       Constructor[] cons = c.getConstructors();  
       //打印的方式你可以自己写,为了方便我用Arrays.toString(),凑合着看  
       System.out.println(Arrays.toString(cons));  
   }  
}

我选择了Boolean类来做例,因为Boolean类的构造方法就两个,方便看。

java中截取字符串_java提取字符串中某个字符_java截取字符串中的一部分

实例6:取得类所实现的接口

import java.util.Arrays;  

public class Demo {  
   public static void main(String[] args) throws Exception {  
       Class c = null;  
       try {  
           c = Class.forName("java.lang.Boolean");  
       } catch (ClassNotFoundException e) {  
           e.printStackTrace();  
       }  
       Class[] in = c.getInterfaces();  
       System.out.println(Arrays.toString(in));  
   }  
}

没什么好说的,看结果:

java中截取字符串_java截取字符串中的一部分_java提取字符串中某个字符

实例7:取得父类

public class Demo {  
   public static void main(String[] args) throws Exception {  
       Class c = null;  
       try {  
           c = Class.forName("java.lang.Boolean");  
       } catch (ClassNotFoundException e) {  
           e.printStackTrace();  
       }  
       //注意了,这里不会是数组,why?  
       Class su = c.getSuperclass();  
       System.out.println(su);  
   }  
}

别忘了,java中是单继承,父类只有一个。

java截取字符串中的一部分_java提取字符串中某个字符_java中截取字符串

实例8:取得类的全部方法

import java.lang.reflect.Method;   

public class Demo {  
   public static void main(String[] args) throws Exception {  
       Class c = null;  
       try {  
           c = Class.forName("java.lang.Boolean");  
       } catch (ClassNotFoundException e) {  
           e.printStackTrace();  
       }  
       Method[] m = c.getMethods();  
       //好吧,这次我就大发慈悲的写个打印列表出来  
       for (int i = 0; i < m.length; i++) {  
           System.out.println(m[i]);  
       }  
   }  
}

截取一部分,看看,意思下就行了……这几个例子都比较简单。

java提取字符串中某个字符_java中截取字符串_java截取字符串中的一部分

实例9:取得本类的全部属性

import java.lang.reflect.Field;   

class Person {  
   private String name;  
   private int age;  
}  

public class Demo {  
   public static void main(String[] args) throws Exception {  
       Class c = null;  
       try {  
           c = Class.forName("Person");  
       } catch (ClassNotFoundException e) {  
           e.printStackTrace();  
       }  
       Field[] f = c.getDeclaredFields();  
       for (int i = 0; i < f.length; i++) {  
           System.out.println(f[i]);  
       }  
   }  
}

getDeclaredFielsd()方法可以获取全部属性,getFields()只能获取公共属性。

java提取字符串中某个字符_java截取字符串中的一部分_java中截取字符串

实例10:获取本类中属性的值

import java.lang.reflect.Field;   

class Person {  
   public String name;  
   private int age;  

   public Person(String name, int age) {  
       this.name = name;  
       this.age = age;  
   }  
}  

public class Demo {  
   public static void main(String[] args) throws Exception {  
       Person p = new Person("zhangsan",12);  

       Class c = p.getClass();  

       //获取公共属性的值  
       Field f1 = c.getField("name");  
       //get(p)表明要获取是哪个对象的值  
       String str = (String) f1.get(p);  
       System.out.println("姓名: " + str);  

       //获取私有属性的值  
       Field f2 = c.getDeclaredField("age");  
       //age是私有属性,所以要设置安全检查为true  
       f2.setAccessible(true);  
       int age = (int) f2.get(p);  
       System.out.println("年龄: " + age);  
   }  
}

要注意的是:setAccessible()方法可以设置是否访问和修改私有属性。

java提取字符串中某个字符_java截取字符串中的一部分_java中截取字符串

坦白说,Java学到现在我还没发现什么能亮瞎我钛金眼的知识在里边。每次都是写一堆繁琐的语法实现个小玩意儿,不然就是拼命调用API,拼命的抛异常,让本身显得不够紧凑的代码变得愈发累赘。如果我喜欢一门语言,在我利用它做出东西来之前,它本身的特性必须能够打动我。显然,Java并不让我快乐,也许很多程序员跟我一样是被迫使用Java的,仅以此来安抚我那颗孤独编码的心,下面接着看内容。

反射的应用

实例11:通过反射修改属性

import java.lang.reflect.Field;   

class Person {  
   private String name;  

   public Person(String name) {  
       this.name = name;  
   }  

   public String toString() {  
       return "姓名: " + this.name;  
   }  
}  

public class Demo {  
   public static void main(String[] args) throws Exception {  
       Person p = new Person("王二狗");  
       System.out.println(p);  
       Class c = p.getClass();  

       //定义要修改的属性  
       Field f = c.getDeclaredField("name");  
       f.setAccessible(true);  
       //修改属性,传入要设置的对象和值  
       f.set(p, "张二蛋");  
       System.out.println(p);  
   }  
}

几个方法都是有联系的,如果看不懂就先熟悉上面几个例子。

java截取字符串中的一部分_java中截取字符串_java提取字符串中某个字符

实例12:通过反射调用方法

import java.lang.reflect.Method;   

class Person {  
   public void print(int i) {  
       System.out.println("我在写数字: " + i);  
   }  

   public static void say(String str) {  
       System.out.println("我在说: " + str);  
   }  
}  

public class Demo {  
   public static void main(String[] args) throws Exception {  
       Person p = new Person();  
       Class c = p.getClass();  

       //getMethod()方法需要传入方法名,和参数类型  
       Method m1 = c.getMethod("print", int.class);  
       //invoke()表示调用的意思,需要传入对象和参数  
       m1.invoke(p, 10);  

       Method m2 = c.getMethod("say", String.class);  
       //这里的null表示不由对象调用,也就是静态方法  
       m2.invoke(null, "你妹");  
   }  
}

这里演示了一个普通的有参方法和一个静态方法。

java中截取字符串_java截取字符串中的一部分_java提取字符串中某个字符

既然有参数的都写出来了,那么无参的就更简单了,直接传入一个对象即可。

实例13:通过反射操作数组

import java.lang.reflect.Array;   

public class Demo {  
   public static void main(String[] args) throws Exception {  
       int[] arr = {1,2,3,4,5};  
       Class c = arr.getClass().getComponentType();  

       System.out.println("数组类型: " + c.getName());  
       int len = Array.getLength(arr);  
       System.out.println("数组长度: " + len);  
       System.out.print("遍历数组: ");  
       for (int i = 0; i < len; i++) {  
           System.out.print(Array.get(arr, i) + " ");  
       }  
       System.out.println();  
       //修改数组  
       System.out.println("修改前的第一个元素: " + Array.get(arr, 0));  
       Array.set(arr, 0, 3);  
       System.out.println("修改后的第一个元素: " + Array.get(arr, 0));  
   }  
}

这里要注意一点,getComponentType()返回的是数组元素的Class。

java中截取字符串_java提取字符串中某个字符_java截取字符串中的一部分

java中截取字符串_java截取字符串中的一部分_java提取字符串中某个字符

(送上一张Java反射机制学习思维导向图)

暂时就写这么多,我看的书中还有反射在工厂模式中的应用,就是用forName()方法替换一下。

往期精选

限时特惠:本站每日持续更新海量展厅资源,一年会员只需29.9元,全站资源免费下载
站长微信:zhanting688