程序员_Java高新技术<一>

 


一、Eclipse的使用:
1.
新建类要有包,包名:公司的网址反过来+包名
例如:com.huawei.day1  cn.xinlang.day2
2.
切换工作间,workspace:file-switch Workspace
3.
双击代码行左边,设置断点,右键,dubug as(调试)进入调试状态,
 右击欲调试的代码行,watch,查看当前值。
单步执行:
step into:进入子函数
step over:越过子函数,但子函数会执行
step out:跳出子函数 
4.
显示某个视图:
window-show view
5.
运行是工程的属性版本要和运行版本一致。
工程属性版本:工程右键-Properties-Java Compiler
运行版本:工程右键-run as-run configuration-JRE

window中设置整个工作台的版本,各个项目默认版本就是该版本,
但也可自己设置,类似继承与被继承的关系

6.
java模板代码:
window-perferences-Java-Ediitor-Templates(模板)-new新建自己的模板
在编程时,alt+/就可通过自定义的模板名调出模板。
7.导入已有的工程。
file-import-General-Existing Projects into Workspace
注意:当导入工程时,若这工程中的JRE库不和自己环境一样,可以删掉再导入自己的jre库
工程右键-Builder Path-Configure Builder Path-Libraries(库)-选中库-删除添加自己的库

另外:也可建立自己的库,导入需要的jar包。

二、小知识点总结:
1.JDK 1.5后:
静态导入:导入一个类中的静态方法。
例如:import static java.lang.Math.*;
max(5,6)//省略前面的Math.

import xxxx 和 import static xxxx的区别是前者一般导入的是类文件如import java.util.Scanner;
后者一般是导入静态的方法,import static java.lang.System.out;

2.overload(重载) vs override(重写):

override(重写) 
1、方法名、参数、返回值相同。
2、子类方法不能缩小父类方法的访问权限。
3、子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。
4、存在于父类和子类之间。
5、方法被定义为final不能被重写。
overload(重载)
1、参数类型、个数、顺序至少有一个不相同。  
2、不能重载只有返回值不同的方法名。
3、存在于父类和子类、同类中。


3.可变参数:如:public static int add(int x,int...args)
      特点:a.只能出现在参数列表的最后。
    b....位于变量类型和变量名之间,前后有无空格都可以

            c.调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,

      在方法体中以数组的形式访问可变参数

   
<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;"> public static int add(int x,int...args)
{

<span style="white-space:pre">	</span>int sum=x;
<span style="white-space:pre">	</span>for(int i=0;i<args.length;i++)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>sum+=args[i];//以数组的形式存在

<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>return sum;
}
</span>


4:增强for循环:for(type 变量名:集合变量名){}
注意:1.此集合必须是实现了Iterator接口,否则不能用,例如HashMap就不能用。
      2.迭代变量必须在()中定义


5.
基本数据的自动拆箱装箱及享元设计模式。
自动装箱:Integer num1=12;
自动拆箱:System.out.println(num1+12);

享元模式:flyweight
<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">String s1=new String("abc");
String s2=new String("abc");
System.out.println(s1==s2);//false,因为s1与 s2是两个不同对象

String s3="a";
String s4="a";
System.out.println(s3==s4);//true,享元模式:为了节约空间,s3与s4占相同的空间,相同的地址


Integer i1=1;
Integer i2=1;
System.out.println(i1==i2);//true,
享元模式:为了节约空间,对于-128~127之间的数,出现的频率比较高,认定此两变量相等


Integer i3=137;
Integer i4=1137;
System.out.println(i3==i4);//false,超出-128~127范围</span>



6.枚举类:实例有限而且固定的类称为枚举类。例如季节,星期几

注意:枚举只有一个成员时,就可以作为一种单例的实现方式
<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">public class EnumTest {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
WeekDay weekDay=WeekDay.FRI;
System.out.println(weekDay);//JDK自动实行toString()方法,而不是返回普通对象的地址
System.out.println(weekDay.name());
System.out.println(weekDay.ordinal());//从0开始的排行

//类中的静态方法
System.out.println(WeekDay.valueOf("SUN"));//返回字符串"SUN"对应的对象。
System.out.println(WeekDay.values().length);//返回枚举类中所有的对象组成数组的长度。


}
public enum WeekDay{
SUN(1),MON(),TUE,WED,THI,FRI,SAT;
//在枚举对象后跟上括号,可指定要用哪个构造方法,不写默认不带参数的构造方法
//定义的所有东西必须 在枚举类元素的后面,且枚举元素后有分号。
//构造方法必须私有,当用到该类时才不能new出新对象。
private WeekDay(){System.out.println("first");}
private WeekDay(int day){System.out.println("Sencong");}

}
public enum WeekDay{
SUN(1),MON(),TUE,WED,THI,FRI,SAT;
//在枚举对象后跟上括号,可指定要用哪个构造方法,不写默认不带参数的构造方法
//定义的所有东西必须 在枚举类元素的后面,且枚举元素后有分号。
//构造方法必须私有,当用到该类时才不能new出新对象。
private WeekDay(){System.out.println("first");}
private WeekDay(int day){System.out.println("Sencong");}

}

//带有抽象方法的枚举
public enum TrafficLamp{
/*因为在枚举类中有抽象方法,最好的方式是定义内部类。
 例:RED(30){}是定义的内部类继承了TrafficLamp类,
 方式是枚举类对象RED+{},(30)是枚举类对象指定初始化时的构造方法,指定time


*/
RED(30){
public TrafficLamp nextLamp(){
return GREEN;
}
},
GREEN(45){
public TrafficLamp nextLamp(){
return YELLOW;
}
},
YELLOW(5){
public TrafficLamp nextLamp(){
return RED;
}
};
public abstract TrafficLamp nextLamp();
private int time;
private TrafficLamp(int time){this.time=time;}

}


}</span>


三、透彻分析反射的基础

Class 类(大写):
1.Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class
2.Class类的实例对象;
对应各个类在内存中的字节码。
一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,
不同的类的字节码是不同的,所以他们在内存中的内容是不同的,这一个个空间分别用一个个的对象来表示,
这些对象显然具有相同的类型,就是Class类型
3.如何得到各个字节码对应的实例对象(Class类型)
(1)类名.class,例如;System.class
(2)对象.getClass(),例如:new Date().getClass()
(3)Class.forName("类名"),例如:Class.forName("java.util.Date")
字节码:它经常被看作是包含一个执行程序的二进制文件



<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">public class ReflectTest {


/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub


String str1="abc";
Class cls1=str1.getClass();
Class cls2=String.class;
Class cls3=Class.forName("java.lang.String");
System.out.println(cls1==cls2);//true
System.out.println(cls1==cls3);//true

System.out.println(cls1.isPrimitive());//是否是基本类型,false
System.out.println(int.class.isPrimitive());//是否是基本类型,true
System.out.println(int.class==Integer.class);//不同的类对应不同的字节码,false
System.out.println(int.class==Integer.TYPE);//Integer中定义一个常量TYPE,表示Integer包装的基本类型对应的字节码,true
System.out.println(int[].class.isPrimitive());//数组是不是原始类型?false
System.out.println(int[].class.isArray());//判断一个class是不是数组,true
//总之,只要在源程序中出现的类型,都有各自的Class实例对象,例如int[],void
}


}</span>



反射:

发射就是把Java类中的各种成分映射成相应的java类,例如,一个
Java类用一个Class类的对象来表示,一个类中的组成部分:
成员变量,方法,构造方法,包等等信息也用一个个的Java类来表示,
就像是汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。
表示java类的Class类显然要提供一系列的方法,来获取其中的变量,
方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,
他们是Field,Method,Contructor,Package等等。

通过调用Class类的方法可以得到这些实例对象后,干什么呢?


Constructor类


代表某个类中的构造方法。
1.得到某个类所有的构造方法:
例子:Constructor[]constructors=Class.forName("java.lang.String").getConstructors();
2.得到某一构造方法。通过指定构造方法中的参数
例子:Constructorconstructior=Class.forName("java.lang.String").getConstructor(StringBuffer.class)
//获得方法时要用到类型
3.创建实例对象:
通常方式:Stiring str=new String(new StringBuffer("abc"));
反射方式:String str=(String)constructor.newInstance(new StringBuffer("abc"));
//调用获得方法时要用到上面相同类型的实例对象。
4.Class.newInstance方法
例子:String obj=(String)constructor.newInstance();
该方法内部得到默认的构造方法,然后该构造方法创建实例对象。
该方法内部的具体代码是怎么写的呢?用到了缓存机制来保存默认构造方法的实例对象。


<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">//String的字节码调用getConstructor()方法返回String类的构造方法,并通过指定参数StringBuffer.class来指定返回哪个构造方法,
Constructor constructor1=String.class.getConstructor(StringBuffer.class);

//构造方法对象constructor调用newInstance()方法,new出新对象,并指定参数,赋给Str2.
//但是注意:在编译上句时,等号右边并不执行结果,也就是构造对象constructor并没有指定是谁的构造方法,那么下句在用时就会出错,必须强制指定(String)
String str2=(String)constructor1.newInstance(new StringBuffer("abc"));
System.out.println(str2.charAt(2));//c</span>


/*自动生成构造函数源代码:右键-source-generateConstructor using field*/


Field类:字段的反射

//Reflect
<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">ReflectPoint pt1=new ReflectPoint(3,5);


//Field取字段,getField("y")得到y字段的值
Field fieldY=pt1.getClass().getField("y");
//fieldY的值是多少?是5,错!fieldY不是对象身上的值,而是类上,要用它去取某个对象上对应的值
//要取出某个对象的某个字段的值,需要指明对象。因为field作为字段类的对象
System.out.println(fieldY.get(pt1));

Field fieldX=pt1.getClass().getDeclaredField("x");
//getField()方法只能得到可见的字段。要访问private的字段,需用getDeclaredField(),Declared为公共的意思,即设为可见

//虽然将x设为可见,但是要想能用,需要setAccessible(),设为可用。accessible为可用的意思
fieldX.setAccessible(true);//setAccessible(true)设置可以使用
System.out.println(fieldX.get(pt1));
</span>




/*总结:

得到的Field对象是对应到类上面的成员变量,不是对应到对象上的成员变量。类只有一个,而该类的实例对象有多个,如果与关联,那关联的是哪个对象呢?所以字段fieldX代表
的是X的定义,而不是具体的x变量。

*/


练习:字段的反射:
将任意一个对象中的所有String类型的成员变量
所对应的字符串内容中的“b”改成“a” 


<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">class ReflectTest
{
public static void main(String[] args)
{
changeStringValue(pt1);
System.out.println(pt1);
//当打印输出一个对象时,系统自动调用其toString方法,打印的是toString方法的返回值
}


}
/*小练习,将字段b改成a*/
private static void changeStringValue(Object obj)throws Exception//传进一个对象
{

Field[] fields=obj.getClass().getFields();
for(Field field:fields)
{
if(field.getType()==String.class){
//因为判断是否是同一个字节码,所以要用“==”
String oldValue=(String)field.get(obj);
String newValue=oldValue.replace('b', 'a');

field.set(obj, newValue);
}

}

} 

}
public class ReflectPoint {
private int x;
public int y;
public String str1="bass";
public String str2="basketball";
public String str3="itcast";
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}

public String toString(){

return str1+"::"+str2+"::"+str3;
}
}
</span>


注意:导包时不要导错,一般com.**是内部用的,java.**是外部用的*/
Method类:
代表某个类中的一个成员方法。

得到类中的一个方法:
例子:Method  charAt=Class.forName("java.lang.String").getMethod("charAt",int.class);
调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke(str,1));
如果传递给Method对象的invoke()方法的第一个参数为null,这说明该Method对象对应的是一个静态方法。



<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">//Str1.charAt(1);
Method methodCharAt=String.class.getMethod("charAt", int.class);
//指定哪个类的字节码调用getMethod方法,在方法中指定该类中的哪个方法(因为可能出现重载方法,故要指明参数类型及个数),
System.out.println( methodCharAt.invoke(str1, 1));//invoke是调用的意思,指定操作哪个对象的charAt方法,及其参数
System.out.println( methodCharAt.invoke(null, 1));//null,此处没有对象,说明此处调用的是不需要对象的方法,即static方法。


//按照JDK1.4,没有可变参数,用数组。str1的charAt的第二个元素c
System.out.println(methodCharAt.invoke(str1, new Object[]{2}));
</span>


反射的方式执行某个类中的main方法

需求:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法,用普通 方式调用完之后,
大家要明白为什么要用反射方法去调呢?

问题:启动java程序的main方法的参数是一个字符串数组,即public static void mian(String[] args),通过反射方式来调用这个mian方法时,如何为invoke方法
传递参数呢?按JDK1.5的语法,当把一个字符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?JDK1.5肯定要兼容JDK1.4的语法,
会按JDK1.4的语法进行处理,即把数组打散成若干个单独的参数,所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null.new String[]{"xxx","yyy"}),
javac只把它当做jdk1.4的语法进行理解,而不把它当做jdk1.5语法解释,因此会出现参数类型不对的情况。


解决方法:
mainMethod.invoke(null.new Object[]{new String[]{"xxx","yyy"}}),
maiMethod.invoke(null,(Object)new String[]{"xxx","yyy"}),
编译器会作特殊处理,编译时不把参数当做数组来看待,也就不会把数组打散成
若干参数了。

<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">String startingClassName=args[0];//可以先通过配置run as configration,给arg[0]传递一个类名,那么arg[0]就表示这个类
Method mainMethod=Class.forName(startingClassName).getMethod("main", String[].class);
mainMethod.invoke(null, new String[]{"111","222"});//错误,JDK1.4对传进的数组进行分解,成两个元素。


mainMethod.invoke(null, new Object[]{new String[]{"111","222"}});
</span>



数组的反射

具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。

代表数组的Class实例对象的getSuperclass()方法返回的父类为Object类对应的Class

基本类型的一维数组可以被当做Object类型使用,不能当做Object[]类型使用,非基本的一维数组,
既可以当做Object类型使用,又可以当做Object[]类型使用。

Arrays.asList()方法处理int[]和String[]时的差异。

<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">/*数组的反射*/

int[] a1=new int[]{1,2,3};
int[] a2=new int[]{};
int[][] a3=new int[2][3];
String[] a4=new String[]{"aa","bb","cc"};
System.out.println(a1.getClass()==a2.getClass());//true,维数、类型都相等,字节码就相等。
//System.out.println(a1.getClass()==a4.getClass());编译错误:getClass()是Object 的方法,,左边 的变量不是一个对象,但右边是String类的对象
//System.out.println(a1.getClass()==a3.getClass());编译错误:getClass()是Object 的方           法,左边的变量不是一个对象,但右边二维数组是一个对象
//换成JDK1.4后上两句编译通过,结果都为false,判断数组的字节码是否相同:类型,维数

System.out.println(a1.getClass().getName());//[i
System.out.println(a1.getClass().getSuperclass().getName());//java.lang.Object
System.out.println(a4.getClass().getSuperclass().getName());//java.lang.Object
//数组的字节码的父类都是Object


Object aObj1=a1;
Object aObj2=a4;
//Object[]aObj3=a1;是错误的的,a1是Object,而当中元素不是
Object[] aObj4=a3;
Object[] aObj5=a4;


//得到数组的元素列表
System.out.println(a1);//不能得到a1中的元素列表
System.out.println(a4);//不能得到a4中的元素列表

System.out.println(Arrays.asList(a1));
//由上面,JDK1.4,Object[]a不接受此int类型,调用JDK1.5方法,即Object aObj1=a1。打印出地址
System.out.println(Arrays.asList(a4));//可以得到列表,即Object[] aObj5=a4;每个字符串也是一个对象

//数组的反射应用
private static void printObject(Object obj) {

Class clazz=obj.getClass();
if(clazz.isArray())
{
int len=Array.getLength(obj);
for(int i=0;i<len;i++)
{

System.out.println(Array.get(obj, i));
}

}else
{
System.out.println(obj);
}

} </span>




ArrayList_HashSet的比较,即Hoshcode分析,


<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">//存入集合HashSet()时,看Hashcode和equals方法
Collection collections=new HashSet();

ReflectPoint pt1=new ReflectPoint(3,3);
ReflectPoint pt2=new ReflectPoint(5,5);
ReflectPoint pt3=new ReflectPoint(3,3);

collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);

pt1.y=7;
//若y的值参与了hashCode()的计算,更改后,再进行集合的删除等会无效,因为在删除时根据此时的哈希值找不到对应的对象了
collections.remove(pt1);
System.out.println(collections.size());
</span>


反射技术开发框架的原理

/*在源程序中不出现框架要调用的类名,因为在写框架时,你的类可能还没写,
但为了能调用你的类,可把你的类名写进一个config.properties配置文件,让框架读取此文件中的类名,
当你的类完成以后,只改动配置文件即可
*/

<span style="font-family:KaiTi_GB2312;font-size:18px;color:#333333;">//InputStream ips=new FileInputStream("config.properties");
/*!!!若不指定绝对路径,默认为工程的根目录文件下找,此处一定要得到配置文件的完整路径, 但完整路径不是硬编码,而是运算出来的。
例如:要得到金山词霸文件下某个配置文件,可用getRealPath()先得到金山词霸根目录,然后用  金山词霸/内部 获得。 
*/

/*最常用的加载文件方式:类加载器加载配置文件,用类加载器在classpath目录下,逐个寻找 这个文件。*/
InputStream ips=
ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");

/*也可用类直接加载:默认路径为该类所在的根目录:这个类调用当然默认路径为这个类所在目录*/
//InputStream ips=ReflectTest2.class.getResourceAsStream("config.properties");

Properties props=new Properties();
props.load(ips);
ips.close();
String className=props.getProperty("className");
Collection collections=(Collection)Class.forName(className).newInstance();
//以上相当于一个框架功能,为利用反射加载一个砸配置文件中注册的类,这个类可能暂时还不存在,等类存在时,只要修改配置文件即可、


//ArrayList_HashSet的比较,即Hoshcode分析,
//存入集合HashSet()时,看Hashcode和equals方法
//Collection collections=new HashSet();

ReflectPoint pt1=new ReflectPoint(3,3);
ReflectPoint pt2=new ReflectPoint(5,5);
ReflectPoint pt3=new ReflectPoint(3,3);

collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);


pt1.y=7;
//若y的值参与了hashCode()的计算,更改后,再进行集合的删除等会无效,因为在删除时根据此时的哈希值找不到对应的对象了
collections.remove(pt1);
System.out.println(collections.size());
//以上相当于一个框架功能,为利用反射加载一个砸配置文件中注册的类,这个类可能暂时还不存在,等类存在时,只要修改配置文件即可、
</span>



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值