黑马程序员 Java自学总结十八 Java高新技术第一天

------ ASP.Net+Android+IO开发.Net培训期待与您交流! ------

总结内容来源于张孝祥老师的Java高新技术


课程大纲
  • eclipse的使用技巧
  • 静态导入
  • 可变参数与for循环增强
  • 基本数据类型的自动拆箱装箱
  • 枚举
  • 反射
  • javabean内省
  • beanutils工具包
  • 注解
  • 泛型
  • 类加载器
  • 代理
  • 线程并发库


eclipse 是一个开放源代码的、基于Java的可扩展开发平台.

myeclipse 是一个用于开发Java, J2EE的 Eclipse 插件集合.

eclipse的使用技巧

新建与转换workspace
     转换:File--->Switch WorkPlace--->要转换的工作间
     新建:File--->Switch WorkPlace--->Other...

新建Project:
     方法1:File---->new----> Java Project
     方法2:左侧Package Explorer空白区右键--->new----> Java Project

新建Package:(先有Project后才能够新建Package)
     方法1:选中Project或Project下的src文件夹右键--->new---->Packege
     方法2:File---->new--->Package--Source Folder选择工程--->包命名
     注意:给包命名时,一般选择公司的网址反转后+.具体有意义的名字,这样做的目的是为了尽量让包下新建的类,在整个Internet上的命名空间中唯一 .

快捷键设置
    路径:Window--->Preferences--->General--->Keys(Content Assist)

Perspective与View的关系
     View:每个具体的小窗口(Eclipse中有2000多个)
     Perspective:为完成某一功能而聚集在一起的多个View的集合
     可在Window菜单下选择Open Perspective和Show View

设置编译环境(javac)和运行环境(java)
     设置整个工作间:Window--->Preferences--->Java--->Compiler(设置javac)和Installed JRE(设置java)
     设置单个工程:选择Project名右键---->Properties--->Java Compiler 和Run/Debug Settings
     注意:高版本的JDK可以运行低版本的JDK编译的程序,但低版本的JDK不能运行高版本的JDK编译的程序 , 就是说JDK是高版本向低版本兼容的 . 工作台的配置和单个项目的配置是继承的关系:单个项目如果没有配置会继承工作台的配置。单个项目如果配置了在会覆盖工作台的配置。

调试程序
    步骤:在要调试的代码行的最前边双击加断点,然后代码区右键--->debug as --->在调试透视图中,选中要查看的变量,右键选择watch . 调试完成后,通过右上角的按钮切换到所需的透视图.

设置模板
    设置路径:Window--->Preferences--->Java--->Editor----Templates
    使用模板:选中要使用模板的代码行,右键选择Surround  With——>选择要使用的模板

Source 和 Refactor
     选中类名或代码区,右键后可选择Source和Refactor条目 . 可实现重命名、抽取方法、重写父类方法、产生构造函数等功能.
将工程导入工作台步骤:
1 . 把该工程文件copy到工作台目录下.
2 . File-->Import--->Existing Projects into WorkSpace--->选择已经copy好的的工程
注意:如果该工程原来的库与现在的不同,则需要通过右键的Build Path条目,先删除导入时默认添加的库,然后选择自己的库.

其他小功能 
alt+/ : 代码补全 , 相关代码联想.
ctrl+shift+/ : 把选中的代码区变成注释
ctrl+shift+\ : 把选中的注释变成正常代码
ctrl+单击类名或者方法 : 查看此类或者方法的源码

静态导入:static import

import语句:可以导入一个类或某个包中的所有类(不包括子包中的类)

import  static 语句:导入一个类中的某个静态方法或所有静态方法。

[java]  view plain copy
  1. <pre name="code" class="java">import static  java.lang.System.*;    
  2. public class StaticImport     
  3. {    
  4.     public static void main(String [] args)    
  5.     {   
  6.       //可以省略类名,直接调用方法  
  7.       out.println("-----staticImport----");    
  8.       long beginTime = currentTimeMillis();  
  9.     }    
  10. }   
  11. </pre><br>  
  12. <pre></pre>  
  13. <pre></pre>  

如果类重名时,就指定具体的包名;如果方法重名时,就指定该方法所属的对象或类 , 来进一步确定这个类或者方法的所属 . 


可变参数:Variable parameter

当一个方法中接受的参数个数不确定时 , 就用到了可变参数 .

写法 : 参数类型  ...  参数名

可变参数使用的注意事项: 

1. 只能出现在参数列表的最后一位;
2. ...位于变量类型和变量之间,前后有无空格均可。
3. 调用参数方法时,编译器为该可变参数隐含创建一个数组(其实,可变参数就是一种数组的简写形式),在方法体中以数组形式访问可变参数。 

[java]  view plain copy
  1. class VariableParameter     
  2. {    
  3.     public static void main(String[] args)     
  4.     {    
  5.         getSum("可变参数1",20);    
  6.         getSum("可变参数2"46844);    
  7.     }    
  8.     public static void getSum(String s,int ...args)    
  9.     {    
  10.         System.out.print(s);  
  11.         System.out.print(",{");  
  12.         for(int i : args){  
  13.             if(args.length!=1)  
  14.                 System.out.print(i+",");  
  15.             System.out.print(i);          
  16.         }  
  17.         System.out.print("}");  
  18.     }    
  19. }  

增强for循环 :
语法:for(参数类型  参数名:集合变量名){……}
注意事项:参数类型前可加修饰符,如加final,以方便内部类访问等;迭代变量必须在()中定义;集合变量名可以是数组或事项了Iterable接口的集合类.

[java]  view plain copy
  1. class VariableParameter     
  2. {    
  3.     public static void main(String[] args)     
  4.     {    
  5.         getSum("可变参数1",20);    
  6.         getSum("可变参数2"46844);    
  7.     }    
  8.     public static void getSum(String s,int ...args)    
  9.     {    
  10.         System.out.print(s);  
  11.         System.out.print(",{");  
  12.         for(int i : args){  
  13.             if(args.length!=1)  
  14.                 System.out.print(i+",");  
  15.             System.out.print(i);          
  16.         }  
  17.         System.out.print("}");  
  18.     }    
  19. }  

基本数据类型的装箱与拆箱:
基本数据类型:byte , short , int , long , char , float , double , boolean ;
对应的包装类:Byte,Short,Integer;Long;Character;Float;Double;Boolean;
装箱:把基本数据类型转换成对应的包装类。
拆箱:把包装类转成对应的基本数据类型。
在装箱和拆箱过程中有一个新特性--享元模式,如下边代码所示:

[java]  view plain copy
  1. class AutoBox     
  2. {    
  3.     public static void main(String[] args)     
  4.     {           
  5.         Integer a = 13;//基本数据类型的装箱    
  6.         System.out.println(i+12);//基本数据类型的拆箱         
  7.         //基本数据类型装箱拆箱的一个特性------(享元模式)    
  8.         //当Integer封装的数据在一个字节之间(-128~127),则只建立一个对象,即享元    
  9.         Integer b = 127;    
  10.         Integer c =127;    
  11.         System.out.println(b == c);//结果为ture    
  12.             
  13.         //当Integer封装的数据超出一个字节,则每个都新建一个对象。       
  14.         Integer d = 128;    
  15.         Integer e = 128;    
  16.         System.out.println(i3 == i4);//结果false    
  17.             
  18.         Integer i5 =Integer.valueOf(3);      
  19.         Integer i6 =Integer.valueOf(3);    
  20.         System.out.println(i5 == i6);//true         
  21.     }    
  22. }    
上边的这种设计模式即为享元模式


枚举:Enum

什么是枚举?

     就是要让某个类型变量的取值 , 只能为若干个固定值,否则,编译器报错 .

为什么要有枚举?
     问题:要定义星期几或者性别的变量,该怎么定义?假设用1-7分别表示星期一到星期日,但有人可能会写成int weekday=0。
     枚举就是要让某个类型的变量的值只能为若干个固定值中的一个,否则,编译器就会报错。枚举可以让编译器在编译时就可以控制程序中填写的非法值,普通变量的方式无法在开发阶段实现这一目标。它跟泛型一样,都是把运行期的错误,提前到编译期来控制,提高了安全性。
     注意:可以创建一个enum类,把它看做一个普通的类。除了它不能继承其他类了。(java是单继承,它已经继承了Enum).


[java]  view plain copy
  1. /* 
  2.  用普通类如何实现枚举功能,定义一个WeekDay的类来模拟枚举功能。 
  3.   
  4.  思路: 
  5.  1.私有构造方法。 
  6.  2.每个元素分别用一个公有静态成员变量表示。 
  7.  3.可以有若干公有方法或抽象方法,例如,要提供nextDay方法必须是抽象的。 
  8.   
  9.  总结:枚举是一种特殊的类,其中每个元素都是该类的一个实例对象。 
  10.  */  
  11. public abstract class WeekDay1 {  
  12.     public final static WeekDay1 SUN = new WeekDay1(){  
  13.         public WeekDay1 nextDay() {  
  14.             return MON;  
  15.         }         
  16.     };  
  17.       
  18.     public final static WeekDay1 MON = new WeekDay1(){  
  19.         public WeekDay1 nextDay() {  
  20.             return SUN;  
  21.         }         
  22.     };  
  23.       
  24.     private WeekDay1(){}  
  25.     public abstract WeekDay1 nextDay();  
  26.     public String toString(){  
  27.         return this == SUN?"SUN":"MON";       
  28.     }  
  29. }  

枚举的基本应用

[java]  view plain copy
  1. public class EnumTest {  
  2.     /** 
  3.      * @param args 
  4.      */  
  5.     public static void main(String[] args) {  
  6.           
  7.         //WeekDay1 weekDay = WeekDay1.MON;  
  8.         //System.out.print(weekDay.nextDay());  
  9.           
  10.         WeekDay weekDay = WeekDay.FRI;  
  11.         //System.out.println(weekDay);  
  12.         System.out.println(weekDay.name());  
  13.         System.out.println(weekDay.ordinal());//获取FRI在枚举中的位置  
  14.         System.out.println(WeekDay.valueOf("SUN"));  
  15.         System.out.println(WeekDay.values().length);//获取枚举内的所有元素并返回数组         
  16.     }  
  17.     //带有构造方法的枚举  
  18.     public enum WeekDay{  
  19.         SUN(1),MON(),TUE,WED,THI,FRI,SAT;  
  20.         private WeekDay(){System.out.println("first");}  
  21.         private WeekDay(int i){ System.out.println("second");}        
  22.     }         
  23. }  

·枚举相当于一个类,其中可以定义构造方法、成员变量、普通方法和抽象方法.
·枚举元素必须位于枚举体中的最开始部分,枚举元素列表的后面要有分号与其他成员分隔.
·把枚举中的成员方法或变量等放在枚举元素的前面,编译器会报告错误.
·枚举的元素是由枚举类的子类来生成的实例对象,这些子类采用类似内部类的方式进行定义
*枚举只有一个成员时,就可以作为一种单例的实现方式.

·枚举的构造方法
1.必须定义成私有.
2.无参的元素默认调用无参的构造方法,有参则调用对应参数的构造方法.
3.枚举元素MON和MON()的效果是一样的,都是调用默认的构造方法.

[java]  view plain copy
  1. public class EnumTest2 {  
  2.   
  3.     /** 
  4.      * @param args 
  5.      */  
  6.     public static void main(String[] args) {  
  7.           
  8.     }  
  9. /* 
  10. 带方法的枚举 
  11. 1.定义枚举Trafficlamp. 
  12. 2.3个元素都需要传入int型的参数调用对应的构造函数. 
  13. 3.3个元素都需要实现Trafficlamp的抽象方法.  
  14. */    
  15.     public enum Trafficlamp{  
  16.         RED(30){  
  17.             public Trafficlamp nextTra() {  
  18.                 return GREEN;  
  19.             }             
  20.         },  
  21.         GREEN(45){  
  22.             public Trafficlamp nextTra() {  
  23.                 return YELLOW;  
  24.             }             
  25.         },  
  26.         YELLOW(5){  
  27.             public Trafficlamp nextTra() {  
  28.                 return RED;  
  29.             }             
  30.         };  
  31.         public abstract Trafficlamp nextTra();  
  32.         private int time;  
  33.         private Trafficlamp(int time){this.time=time;}  
  34.     }  
  35. }  

当枚举只有一个成员时,就可以作为一个单例的实现方式。


反射

反射 : 就是把Java类中的各种成分映射成对应的java类.
例如:
变量类Field
方法类Method
构造方法类Contructor
包类Package

反射的基石→Class类
  • Java程序中的各个类也属于同一类事物,描述这类事物的Java类名就是Class
  • 对比说明:众多的人用什么类来表示? 众多的类用什么来表示?
          人→Person
          类→Class
  • 对比说明:Person类代表人,它的实例对象就是张三、李四这样一个个具体的人,Class类代表Java类,它的实例对象又分别对应什么呢?
          Class类的实例对象对应的是各个类在内存中的字节码.不同类的字节码是不同的.
  • 如何得到各个字节码对应的实例对象(Class类型)
          1.类名.class,例如:System.class
          2.对象.getClass().例如:new String().getClass()
          3.Class.forName("类名"),例如:Class.forName("java.util.Date");
  • 九个预定义Class实例对象
boolean, byte, char, short, int, long, float,double, void
通过 字节码.isPrimitive() 方法来判断是否是基本数据类型
基本数据类型包装类的常量TYPE代表所包装的基本数据类型字节码
例如:int.class==Integer.TYPE的结果为true.
  • 数组类型的Class实例
          通过 字节码.isArray() 来判断是否为数组

总之:只要是在源程序中出现的类型,都有各自的Class实例.

反射→Constructor类

Constructor类代表某个类中的一个构造方法
  • 得到某个类所有的构造方法:
          例如:获取String类的所有构造方法
          Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
  • 得到某个类的某个构造方法 : getConstructor(Class<?>... );
          例如:获取String类中参数为StringBuffer的构造函数
          Constructor<String> constructor = String.class.getConstructor(StringBuffer.class);
  • 利用获取的构造方法创建该类的实例 : newInstance(Object obj);
          例如:获取constructor所属类的实例          
          String s = constructor.newInstance(new StringBuffer("abc"));

注意:用newInstance()方法获取实例时,方法中的参数必须和原构造函数的参数一致,否则会发生异常!

Class类中也有newInstance()方法,该方法是得到默认的构造方法,然后用构造方法创建实例对象.
用法是 : 字节码.newInstance();

代码
[java]  view plain copy
  1. package com.itheima;  
  2. import java.lang.reflect.Constructor;  
  3.   
  4. public class ConstructorDemo {  
  5.       public static void main(String[] args) throws Exception{  
  6.               
  7.             Constructor<String> constructor = String.class.getConstructor(StringBuffer.class);  
  8.             String str = constructor.newInstance( new StringBuffer("abc"));  
  9.             System. out.print(str.charAt(2));  
  10.       }  
  11. }  

反射→Field类

Field类代表某一个类中的一个成员变量

变量非私有时    
  • 获取某个对象的某个成员变量对象 :
          Field filedX = 对象.getClass().getField("x");
          注意 : 获取到的fieldX只是这个对象所属类的变量的对象 , 而非具体变量值.
  • 那么如何获取这个变量在某个对象中的值呢?
          方法示例 : fieldX.get(对象);

变量私有private时     
  • 获取某个对象的某个成员变量对象 : 
          Field filedX = 对象.getClass().getDeclaredField("变量名");
  • 取得某个变量在对象中的值
          因为变量为私有,所以要先用setAccessible(true)方法设置为可访问 :  
          fieldX.setAccessible(true);
          然后 : fieldX.get(对象);
          就能取出私有变量在具体对象中的值 , 上面的方法又叫暴力反射

代码

[java]  view plain copy
  1. package com.itheima;  
  2. import java.lang.reflect.Field;  
  3. class WhyNot{  
  4.       private int x;  
  5.       public int y;  
  6.       public WhyNot( int x, int y) {  
  7.              super();  
  8.              this. x = x;  
  9.              this. y = y;  
  10.       }  
  11. }  
  12. class FieldDemo{  
  13.       public static void main(String[] args) throws Exception{  
  14.             WhyNot wn = new WhyNot(3,5);  
  15.             Field fieldY = WhyNot. class.getField( "y");  
  16.             System. out.println(fieldY); //结果为y  
  17.             System. out.println(fieldY.get(wn)); //结果为5  
  18.               
  19.              //取出私有的变量x  
  20.             Field fieldX = WhyNot. class.getDeclaredField( "x");  
  21.             System. out.println(fieldX); //结果为x  
  22.             fieldX.setAccessible( true); //设置变量x为可访问  
  23.             System. out.println(fieldX.get(wn)); //结果为3            
  24.       }  
  25. }  

Field练习→替换变量中的某个字符

[java]  view plain copy
  1. import java.lang.reflect.Field;  
  2. /* 
  3. 需求:扫描对象中所有变量,是否为String类型,是把字符串中的'b'换成'a'. 
  4. */  
  5. class TestString{  
  6.       public String str1 = "ball";  
  7.       public String str2 = "basketball";  
  8.       public String str3 = "itcast";        
  9. }  
  10. public class FIeldTest {  
  11.       public static void main(String[] args) throws Exception {  
  12.             TestString ts = new TestString();  
  13.              //获取所有变量,返回Field数组  
  14.             Field[] fields = ts.getClass().getFields();  
  15.              //高级for循环遍历  
  16.              for(Field field : fields){  
  17.                    //判断变量类型是否为String  
  18.                    if(field.getType() == String. class){  
  19.                          //向下转型为String类型  
  20.                         String oldValue = (String)field.get(ts);  
  21.                          //调用String类中的replace方法  
  22.                         String newValue = oldValue.replace( 'b''a');  
  23.                          //把修改后的字符串重新赋值给 ts对象的变量  
  24.                         field.set(ts, newValue);  
  25.                         System. out.println(field.get(ts));  
  26.                   }  
  27.             }  
  28.       }  
  29. }  
反射→Method类

Method类代表某个类中的一个成员方法
  • 得到类中的某一个方法
          例子 : Method charAt = Class.forName(java.lang.String).getMethod("charAt",int.class);
  • 调用方法
          charAt.invoke(对象 , 1);
          注意 : 如果传递给Method对象的invoke()方法的对象参数是null , 说明该Method方法是一个静态方法.

代码
[java]  view plain copy
  1. package com.itheima;  
  2. import java.lang.reflect.Method;  
  3.   
  4. public class MethodDemo {  
  5.       public static void main(String[] args) throws Exception{  
  6.             String str = "abc";  
  7.              //获取String类的charAt方法  
  8.             Method md = String. class.getMethod( "charAt"intclass);  
  9.              //调用方法  
  10.             System. out.println(md.invoke(str, 1));  
  11.              //jdk1.4调用方法的参数是一个Object数组  
  12.             System. out.println(md.invoke(str, new Object[]{2}));  
  13.       }  
  14.   
  15. }  

Method练习→执行类的main方法
[java]  view plain copy
  1. import java.lang.reflect.Method;  
  2. /* 
  3.  目标:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法. 
  4. */  
  5. public class MethodTest {  
  6.   
  7.       public static void main(String[] args) throws Exception{  
  8.              //假定main方法传进来的参数是一个完整的类名  
  9.             String startingClassName = args[0];  
  10.              //获取这个类的main方法  
  11.             Method mainMethod = Class.forName(startingClassName).getMethod( "main", String[]. class);  
  12.              //有下面两种方式来使用main方法  
  13.             mainMethod.invoke( nullnew Object[]{ new String[]{"aa","bb" ,"cc" }});  
  14.              //mainMethod.invoke(null, (Object)new String[]{"aa","bb","cc"});  
  15.       }  
  16. }  
  17.   
  18. class TestArguments{  
  19.       public static void main(String[] args){  
  20.              for(String arg : args){  
  21.                   System. out.println(arg);  
  22.             }  
  23.       }  
  24. }  

数组与Object的关系及其反射类型


数组的反射
  • 具有相同维数和元素类型的数组属于同一个Class类型 , 具有相同的Class实例对象.
  • 所有数组的Class实例对象的getSuperclass()方法返回的父类都是Object类对应的Class实例对象 . 既所有数组都可以说成是Object类型的.
  • 基本类型的一维数组可以被当成Object类型使用 , 不能当作Object[]类型使用 ; 例如 : int[]可以是Object , 但不能是Object[] ; 非基本类型的一维数组 , 既可以当作Object类型使用 , 又可以当作Object[]类型使用.
  • Arrays.asList()方法处理int[]和String[]时的差异.
  • int[]被当成一个Object元素存进集合 , String[]被当成一个Object[]数组 , 数组的元素被拆开后存进集合.
反射→Array类
直接用代码来说明

[java]  view plain copy
  1. package com.itheima;  
  2. import java.lang.reflect.Array;  
  3. public class Test {  
  4.       public static void main(String[] args) {  
  5.              int[] a1 = new int[]{1,2,3};  
  6.             String[] strs = new String[]{ "a""b"};  
  7.             String str = "xy";  
  8.               
  9.              printObject(a1);  
  10.              printObject(strs);  
  11.              printObject(str);  
  12.       }        
  13.       public static void printObject(Object obj){  
  14.              Class c = obj.getClass();  
  15.             System. out.println(c.getName());  
  16.              //判断c的字节码是否为数组  
  17.              if(c.isArray()){  
  18.                    //Array类中的方法全部都是静态,直接调用获取数组长度的方法  
  19.                    int len = Array. getLength(obj);  
  20.                    forint x = 0; x < len; x++){  
  21.                          //用Array类中的get()方法遍历出数组中的元素  
  22.                         System. out.println(Array. get(obj, x));  
  23.                   }  
  24.             }  
  25.              else  
  26.                   System. out.println(obj);  
  27.       }  
  28. }  

hashCode的作用和产生内存泄漏的原因
       当一个对象被存储进hashSet集合以后,就不能再修改对象中的那些参与计算哈希算法的那些字段,否则会造成内存泄露。表面上程序代码在不 断增加对象,删除对象,但实际内存中并没有删除,该对象以后不再用了,可是内存中却一直存在,造成浪费,最终导致内存泄露。

反射的作用
Java反射的作用
假如我们有两个程序员,一个程序员在写程序的时候,需要使用第二个程序员所写的类,但第二个 程序员并没完成他所写的类。那么第一个程序员的代码能否通过编译呢?这是不能通过编译的。利用Java反射的机制,就可以让第一个程序员在没有得到第二个 程序员所写的类的时候,来完成自身代码的编译 .
Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对大家以后学习框架技术有很大的帮助。

简单的框架代码
[java]  view plain copy
  1. import java.io.*;  
  2. import java.util.*;  
  3. public class HashTest {  
  4.       public static void main(String[] args) throws Exception{  
  5.              //输入流读取配置文件  
  6.             InputStream is = new FileInputStream( "config.properties");  
  7.             Properties props = new Properties();  
  8.              //加载输入流  
  9.             props.load(is);  
  10.              //关闭流  
  11.             is.close();  
  12.              //根据key,取出vlaue(类名)  
  13.             String className = props.getProperty( "className");  
  14.              //创建该类的实例对象,并向下转型  
  15.              Collection collections = (Collection)Class.forName(className).newInstance();  
  16.             Hash h1 = new Hash(3,3);  
  17.             Hash h2 = new Hash(3,5);  
  18.             Hash h3 = new Hash(3,3);  
  19.              collections.add(h1);  
  20.              collections.add(h2);  
  21.              collections.add(h3);  
  22.              collections.add(h1);  
  23.             System. out.println(collections.size());  
  24.       }  
  25. }  
  26. class Hash{  
  27.       private int x;  
  28.       public int y;  
  29.       public Hash(int x, int y) {  
  30.              super();  
  31.              this. x = x;  
  32.              this. y = y;  
  33.       }  
  34. }  
配置文件config.properties内容:
className=java.util.ArrayList

注意:在实际开发中,配置文件获取不是用相对路径,而是绝对路径。


用ClassLoader管理资源和配置文件

        在java程序里,要加载配置文件的时候或任何需要用到路径的时候不要使用相对路径,因为相对路劲是相对当前工作目录,但当前工作目录不是固定不变的,所以要用绝对路径,但不应该在代码里写死,应该用代码在运行时运算出来的 .

       除了直接拼接绝对路径,如果配置文件与类文件在同一个目录 , 可以先通过Class类的非静态方法getClassLoader获取类加载器ClassLoader ,然后通过类加载器ClassLoader的非静态方法getResouceAsStream(“文件名”)方法获取 。也有相对和绝对之分,如果参数字符串以‘/’开头表示绝对,不是的话就表示相对,这里绝对是从根目录开始的绝对路径(不是以盘符开始的绝对),相对是相对加载类所在的路径。
       Class类中也有getResouceAsStream("文件名")方法 , 此方法内部就是调用了类加载器ClassLoader的相同方法 .
  • 我们把config.properties文件和TestReflect.java放在同一目录下时:
   InputStream is = TestReflect.class.getClassLoader().getResourceAsStream("com/itcast/config.properties");
这种方式首先找到TestReflect这个类,然后拿到该类的加载器,再由类加载器去加载资源文件。 
  • config.properties文件和TestReflect.java依旧位于同一目录下:
InputStream is = TestReflect.class.getResourceAsStream("config.properties");
这种方式是类加载器的简化形式,这时是用的相对路径的形式。 
  • config.properties位于com.itcast.resource包下时:
InputStream is = TestReflect.class.getResourceAsStream("resource/config.properties");
这种方式和方法二类似,也是用的对路径的形式 
  • config.properties位于com.itcast.resource包下时:
InputStream is = TestReflect.class.getResourceAsStream("/com/itcast/resource/config.properties");
这种方式用的是绝对路径(简化的类加载器也可以使用绝对路径)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值