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

来源:互联网 发布:linux dhcp option 67 编辑:程序博客网 时间:2024/05/20 20:57

----------------------<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 虚拟机创建,与其表示的基本类型同名,即 booleanbytecharshortintlongfloatdouble

数组类型的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 =newint [3];

        int[] a2 =newint [4];

        int [][] a3 =newint[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>、期待与您交流! ----------------------


0 0
原创粉丝点击