您的位置:首页 > 职场人生

黑马程序员_Java基础提高笔记1

2014-03-17 09:37 579 查看

----------------------<ahref="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<ahref="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------

黑马程序员_Java基础提高笔记1

反射的基石->Class

Class-à代表一类什么样的事物?(属性)

但是属性值是由这个类的实例来实现

Class: java程序中的各个 java类属于同一事物,描述这类事物的java类名就是class

Person p1 = new Person();

Person p2 = new Person();

Class cls1 = Date.class字节码1;

Class cls2 = Person.class字节码2;

得到类的字节码的方式:

1.System.class

2.对象.getClass()

3.class.forName(“类名”):反射时常用到,在写源程序时候不知道类的名字

P1.getClass();

Class.forName(“java.lang.String”):

有九种预定义的
Class
对象,表示八个基本类型和 void。这些类对象由 Java 虚拟机创建,与其表示的基本类型同名,即
boolean
byte
char
short
int
long
float
double


数组类型的class实例对象: class.isArray()

只要在源程序中出现的类型,都有各自class实例对象

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

System.out.println(cls1.isPrimitive());
System.out.println(int .class.isPrimitive());
System.out.println(int.class == Integer.class);
System.out.println(int.class == Integer.TYPE);
System.out.println(int[].class.isPrimitive());
System.out.println(int[].class.isArray());
//new String(new StringBuffer("abc"));用反射表示如下
Constructor constructor1 =String.class.getConstructor(StringBuffer.class);
String str2 =(String)constructor1.newInstance(new StringBuffer("abc"));
System.out.println(str2.charAt(2));

反射:就是把java类中的各种成分映射到相应的java类

Constructor类:构造方法

1得到某个类所有的构造方法://方法是由字节码提供,所有的构造方法时装在数组里的

例子:Constructor [] constructors =Class.forName(“java.lang.String”).getConstructor();

2 得到某一个构造方法

例子:Constructor constructor =

Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);//获得方法时要用到类型

3.创建实例对象:

通常方式:String str = new String(newStringBuffer(“abc”));

反射方式:String str =(String)constructor.newInstance(new StringBuffer(“abc”));

//调用获得的方法时要用到上面相同类型的实例对象

4Class.NewIstance()方法:

例子:String obj= (String)Class.forName(“java.lang.String”).newInstance();

ReflectPointpt1 =new ReflectPoint(3,5);
FieldfieldY = pt1.getClass().getField("y");
//fieldY的值是多少?5?错 fieldY不是代表某个对象身上的变量值,而是类上,要用他去取某个对象对应的值
System.out.println(fieldY.get(pt1));
Field fieldX=pt1.getClass().getDeclaredField("x");//因为“x”被private了即私有了,所以要用getDeclaredField()
fieldX.setAccessible(true);//要让他可见但是也要让他可获取,用setAccessible(true):暴力反射
System.out.println(fieldX.get(pt1));

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

changeStringValue(pt1);
System.out.println(pt1);
}
private
static void
changeStringValue(Object obj)throws Exception{
Field[] fields =obj.getClass().getFields();//获取某个类字节码中的成员变量
for(Field field : fields){
//if(field.getType().equals(String.class)):对字节码比较用“=”比,虽然equals也行

if(field.getType()==String.class){
String oldValue=(String)field.get(obj);//获取对象的字符串
String newValue=oldValue.replace('b','a');//替换
field.set(obj, newValue);//之前替换并没把对象身上字符改变,现在设置才改

}
}

Method类代表某个类中的一个成员方法

MethodmehtodCharAt =String.class.getMethod("charAt",int.class);

System.out.println(mehtodCharAt.invoke(str1,1));//invoke是方法对象上的方法
//如果传递给Method对象的invoke()方法的第一个参数是null,那么该Method对象对应静态方法
System.out.println(mehtodCharAt.invoke(str1,new Object[]{2}));
//这是1.4的方法,因为1.4以前没有自动封装功能

例题:写一个程序能根据用户提供的雷鸣,去执行该类中的main方法

//TestArguments.main(newString[]{"111","222","333"});
//但是正常情况下是不知道类名
String startingClassName =args[0];//如果不设置,无法获得类名,则显示数组角标越界
Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);//参数是string类型的数组
mainMethod.invoke(null,new Object[]{new String[]{"111","222","333"}});//main方法时静态的所以不用传递类型
//jdk受到new string[]会把它打开,不把他当成一个数组,会认为是三个参数,所以外面要再加一个new Object[]{}打包(因为他只拆包一次)
//数组在1.4之前被认为是多个参数
//还可以直接写成mainMethod.invoke(null,(Object)new String[]{"111","222","333"});

class TestArguments{
public
static void
main(String[] args){
for(String arg : args){
System.out.println(arg);
}
}

}
如何给类中main()方法字符串数组参数String[] args,以至于可以在main()方法中直接调用该字符串。

在Java程序区域右击--> Run As -->Run Configuration(运行相关配置)
--> 在Argument栏中,填入需要传递的实参,该实参将传递给类mai()方法


数组的反射:
int [] a1 =new
int
[3];
int[] a2 =new
int
[4];
int [][] a3 =new
int
[2][3];
String [] a4 = new String[3];
System.out.println(a1.getClass() == a2.getClass());
//System.out.println(a1.getClass() ==a4.getClass());在jdk1.5以下版本是可以比较的结果为false
//System.out.println(a1.getClass() ==a3.getClass());但是在1.5以后是没法比较的
false
/*对于数组类型的变量
编译器在编译时,其实已经知道类型了。也就是说,编译器认为这2个类型是不一样的。根本没有比较的需要。对于总是不成立的比较,其实是没有意义的。
这个编译错误是 JDK 1.6的新功能
*/
System.out.println(a1.getClass().getName());
System.out.println(a1.getClass().getSuperclass().getName());
System.out.println(a4.getClass().getSuperclass().getName());

Object ab1 =a1;
Object ab2 =a4;
//Object[] ab3 =a1;//基本类型不是Object
Object[] ab4 =a3;
Object[] ab5 =a4;

System.out.println(a1);
System.out.println(a4);
System.out.println(Arrays.asList(a1));//int是基本类型
System.out.println(Arrays.asList(a4));

public
class
ReflectTest2 {
public
static void
main(String[] args) {
Collection collections = newHashSet();
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;
collections.remove(pt1);//该对象的哈希值已经改变,所以移除的并不是原来对象。常时间
//出现这种情况会出现“内存泄漏”
System.out.println(collections.size());
}

}

比较符: == : 是根据对象的值来比较的。

equals(): 是根据所比较的对象的哈希码来比较的。哈希码通常是根据内存地址换算来的。

如果==比较结果是true,那么equals()方法得到的必然也是true,但是,反之则不一定成立。

但是,当两个对象的值相等,但是哈希值不等,即默认的equals()方法下,他们并不相等,那么,如何编程覆盖equals()方法,使之相等?其实,

是指如果两个对象相等,那么只存储其中一个。

Eclipse中提供了快速覆盖equals()的方法,右击 --> Source --> GenerateHashCode() and equals() --> 选择比较的变量。
----------------------<ahref="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<ahref="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: