javase_18(回顾与反射机制学习)

来源:互联网 发布:js获取ip地址全部代码 编辑:程序博客网 时间:2024/05/16 13:46

AM上午总结:

package com.java.kudy.day17_2.ObjectReview;  public class ObjectTest {      /**      *虚拟机做了什么事情?      *1.在栈内存中定义了一个变量p      *2.在类加载器中加载Person.class      *3.在堆内存中开辟空间,分配了一个物理地址      *4.初始化成员变量,如果没有初始值,那么虚拟机会自动初始化,所有的引用数据类型都为null      *5.调用构造函数,为成员赋值(field)      *6.将对象的首地址给变量p2      */     public static void main(String[] args)     {         Person p = new Person("小细",18);              } }  class Person {     private String name;     private int age;     public Person(){}     public Person(String name,int age)     {         this.name = name;         this.age = age;     }          @Override     public String toString()     {         return name+"~"+age;     } }

抽象类的回顾:

package com.java.kudy.day17_2.Extends;  public class ExtendsTest { /*  * 抽象类:  * 1.用abstract修饰的类叫做抽象类  * 2.如果该类有抽象的方法,这个类必须要定义成抽象类  * 3.抽象类是更好的为了多态而服务,我们在设计软件的时,会有一些列类都具备相同的功能,这时方法一样的声明,即使是方法也可以复用.  * 我们应该抽象出一个抽象的父类,方便别人学习软件,也能实现一部分代码.说白了就是:更好的为了多态而服务.  * 4.继续抽象类需要实现抽象方法,或者把继承过来的类定义成抽象类.  */     public static void main(String[] args) {          }  }  abstract class Student {     public abstract void run(); }

接口和内部类的简单复习:

package com.java.kudy.day17_2.Extends;  /*  * 接口:一种特殊的抽象类,所有的方法都是抽象的.  * 1.实现接口用关键字:implements.可以实现多个接口,接口继承接口可以使用extends 关键字  * 2.接口中的所有的方法默认为:public abstractor 共同修饰,所以不需要另外声明  * 3.接口中所有的变量默认为常量:public static final所修饰,不需要声明(一份)  *   * 匿名内部类实现:  * new fulei(){  *     //内部类的定义  * };  * final关键字:  * 1.修饰变量成常量.  * 2.修饰类不能被继承.  * 3.修饰方法不能被重写.  */ public class InterfacesTest {       public static void main(String[] args) {         Teacher kudy = new Teacher(){             @Override             public void teching() {                 System.out.println("同学们,其实我什么也不懂~~!");             }             //匿名内部类实现                      };     }  }  interface Teacher {     void teching();  //public abstract void teching(); }   package com.java.kudy.day17_2.Extends;  public class ExtendsDemo { /*使用extends关键字,让子类继承父类  * 1.子类会自动复用于父类的方法  * 2.可以把一个子类的实例当做父类来使用,调用方法时,是调用子类的方法(多态),但必须是重写了父类的方法,不过可以转型.访问属性是访问父类的  * (静态绑定,-->在编译的期间就已经完成了变量的绑定)而访问方法是访问子类的(动态的绑定-->)  * 如果是调用子类特有的方法,需要强制转换成子类的类型.  * 假设:A的父类是B B的父类的C  -->  如果父类型的C 引用指向子类型的对象-->A  * 但我想使用B类型的方法,我们只需要把B b = (B)c;强制转换就可以.因为c对象本来就是A.  * 3.子类的实例化: 子类在实例化过程中一定调用父类的构造方法,我们在子类的构造函数的第一行可以用this(实参)调用自己的其他方法,  * Super(实参)调用父类的某个构造方法,如果第一行什么也不写.默认super()调用父类的不带参数的构造方法  * 4子类覆盖父类的方法: 方法名相同,参数类型相同.方法的返回值也必须要相同.      *   */     public static void main(String[] args) {             C c = new A();             //如果我想调用b的方法,原因: 我是你A的父类             B b = (B)c;             b.run();             b.happy();     }  } class C {     public void run()     {         System.out.println("a");     } }  class B extends C {     public void run()     {         System.out.println("b");     }     public void happy()     {         System.out.println("我是happy达人");     } }  class A extends B {     public void run()     {         super.run();         System.out.println("c");     } }

ArrayList(元素有序,底层数组实现.)

package com.java.kudy.day17_2.CollectionTest;  import java.util.ArrayList; import java.util.Iterator;  import com.java.kudy.day17_2.reflectDemo.Person;  public class ArrayListTest {      public static void main(String[] args)     {         ArrayList<Person> al = new ArrayList<Person>();         al.add(new Person("a",1));         al.add(new Person("b",2));         al.add(new Person("c",3));         al.add(new Person("d",4));         al.add(new Person("e",5));                  /*          * 迭代的三种方式:          */         Iterator<Person> it = al.iterator();         while(it.hasNext())         {             Person p = it.next();             System.out.println(p);         }                  for(Person p : al)             System.out.println(p);                  for(int i=0; i<al.size(); i++)         {             System.out.println(al.get(i));         }     }  }  package com.java.kudy.day17_2.CollectionTest;  import java.util.HashSet;  import com.java.kudy.day17_2.reflectDemo.Person;  public class HashSetTest {     /*      * 通过哈希算法保证元素没重复性      * 首先通过哈希算法比较,再用equals比较.      * 1.hashCode      * 2.equals      */     public static void main(String[]args)     {         HashSet<Person> al = new HashSet<Person>();         al.add(new Person("a",1));         al.add(new Person("b",2));         al.add(new Person("c",3));         al.add(new Person("d",4));         al.add(new Person("a",1));                  for(Person p : al)             System.out.println(p);     } }

TreeSet:可以写比较器..(如果没有实现接口的方法,会出异常信息)


package com.java.kudy.day17_2.CollectionTest;  import java.util.Comparator; import java.util.TreeSet;  import com.java.kudy.day17_2.reflectDemo.Person;  public class TreeSetTest {     public static void main(String[]args)     {         TreeSet<Person> ts = new TreeSet<Person>(new Comparator<Person>(){              @Override             public int compare(Person s1, Person s2) {                 int num = s1.getAge()-s2.getAge();                 if(num!=0)                     return num;                 return s1.getName().compareTo(s2.getName());             }                      });         ts.add(new Person("a",1));         ts.add(new Person("b",2));         ts.add(new Person("c",3));         ts.add(new Person("d",4));         ts.add(new Person("a",1));         for(Person p :ts)             System.out.println(p);     } }

Map回顾练习:

package com.java.kudy.day17_2.CollectionTest;  import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; import java.util.Set;  public class HashMapTest {      /**      * @param args      */     public static void main(String[] args)     {         HashMap<Teacher, Integer> hm =                     new HashMap<Teacher, Integer>();         hm.put(new Teacher("a",1), 1);         hm.put(new Teacher("a",1), 1);         hm.put(new Teacher("b",2), 1);         hm.put(new Teacher("c",3), 1);         //保证了key的无重复性              /*    //方式一:         Set<Entry<Teacher, Integer>> entrys = hm.entrySet(); //获取一个试图         Iterator<Entry<Teacher, Integer>> it = entrys.iterator();         while(it.hasNext())         {             Entry<Teacher, Integer> e = it.next(); //迭代器,迭代下一个内容             Teacher key = e.getKey();             Integer value = e.getValue();             System.out.println(key +"--"+value);         }*/                  //方式二:         Set<Teacher> keys= hm.keySet();         for(Teacher t : keys)         {             Integer value = hm.get(t);             System.out.println(t+"--"+value);         }              }   }

Properties的应用:

package com.java.kudy.day17_2.CollectionTest;  import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.PrintStream; import java.util.Enumeration; import java.util.Properties;  public class PropertiesTest {      /**      * @param args      * 用于读写配置文件      * @throws IOException       * @throws FileNotFoundException       */     public static void main(String[] args) throws FileNotFoundException, IOException {         Properties prop = new Properties();         prop.load(new FileReader("src/a.properties")); //读取进来         Enumeration e = prop.propertyNames();                  //通过枚举获取到键-->值         while(e.hasMoreElements())         {             String key = (String)e.nextElement();             String value = prop.getProperty(key);             System.out.println(key+"----"+value);         }                  //   调用 Hashtable 的方法 put  键和值进来   key  value         prop.setProperty("name","my_kudy");         prop.setProperty("age", "19");         //直接把内容打印到一个配置文件里面去         prop.list(new PrintStream("src/a.properties")); //直接把字节和字符写入进去         //把内容输入里面去     }  }

PM下午总结:

JAVA语言中的反射机制:
    在Java 运行时 环境中,对于任意一个类,能否知道这个类有哪些属性和方法?
    对于任意一个对象,能否调用他的方法?这些答案是肯定的,这种动态获取类的信息,以及动态调用类的方法的功能来源于JAVA的反射。从而使java具有动态语言的特性。

  JAVA反射机制主要提供了以下功能:
      1.在运行时判断任意一个对象所属的类
      2.在运行时构造任意一个类的对象
      3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法)
      4.在运行时调用任意一个对象的方法(*****注意:前提都是在运行时,而不是在编译时)

  Java 反射相关的API简介:
      位于java。lang。reflect包中
        --Class类:代表一个类
        --Filed类:代表类的成员变量
        --Method类:代表类的方法
        --Constructor类:代表类的构造方法
        --Array类:提供了动态创建数组,以及访问数组的元素的静态方法。该类中的所有方法都是静态方法


----Class类
     在 java 的Object类中的申明了数个应该在所有的java类中被改写的methods:
hashCode(), equals(),clone(),toString(),getClass()等,其中的getClass()返回yige
Class 类型的对象。
     Class类十分的特殊,它和一般的类一样继承自Object,其实体用以表达java程序运行
时的 class和 interface,也用来表达 enum,array,primitive,Java Types 以及关键字void
,当加载一个类,或者当加载器(class loader)的defineClass()被JVM调用,便产生一个Class
对象,
     Class是Reflection起源,针对任何你想探勘的class(类),唯有现为他产生一个Class
的对象,接下来才能经由后者唤起为数十多个的反射API。


     Java允许我们从多种途径为一个类class生成对应的Class对象。
          --运用 getClass():Object类中的方法,每个类都拥有此方法
                                String str="abc";
                                Class cl=str.getClass();


         --运用 Class。getSuperclass():Class类中的方法,返回该Class的父类的Class
         --运用 Class。forName()静态方法:
         --运用 ,Class:类名.class
         --运用primitive wrapper classes的TYPE语法: 基本类型包装类的TYPE,如:Integer.TYPE
                      注意:TYPE的使用,只适合原生(基本)数据类型

----运行时生成instance
     想生成对象的实体,在反射动态机制中有两种方法,一个针对无变量的构造方法,一个针对带参数的
构造方法,,如果想调用带参数的构造方法,就比较的麻烦,不能直接调用Class类中的newInstance()
,而是调用Constructor类中newInstance()方法,首先准备一个Class[]作为Constructor的参数类型。
然后调用该Class对象的getConstructor()方法获得一个专属的Constructor的对象,最后再准备一个
Object[]作为Constructor对象昂的newInstance()方法的实参。
      在这里需要说明的是 只有两个类拥有newInstance()方法,分别是Class类和Constructor类
Class类中的newInstance()方法是不带参数的,而Constructro类中的newInstance()方法是带参数的
需要提供必要的参数。

package com.java.kudy.day17_2.reflectDemo;  import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier;  public class ClassTest {      /**      * @param args      * 反射的引用:      * ----Class类     在 java 的Object类中的申明了数个应该在所有的java类中被改写的methods:     hashCode(), equals(),clone(),toString(),getClass()等,其中的getClass()返回一个         Class 类型的对象。     Class类十分的特殊,它和一般的类一样继承自Object,其实体用以表达java程序运行     时的 class和 interface,也用来表达 enum,array,primitive,Java Types 以及关键字void     ,当加载一个类,或者当加载器(class loader)的defineClass()被JVM调用,便产生一个Class     对象,     Class是Reflection起源,针对任何你想探勘的class(类),唯有现为他产生一个Class     的对象,接下来才能经由后者唤起为数十多个的反射API。     的类      * @throws ClassNotFoundException       * @throws NoSuchFieldException       * @throws SecurityException       * @throws IllegalAccessException       * @throws IllegalArgumentException       * @throws NoSuchMethodException       * @throws InvocationTargetException       * @throws InstantiationException       */     public static void main(String[] args) throws ClassNotFoundException,                                 SecurityException, NoSuchFieldException,                                  IllegalArgumentException, IllegalAccessException,                                 NoSuchMethodException, InvocationTargetException,                                 InstantiationException     {         Object obj = new Person();                  //获取实例三中方法         //通过对象.getClass获取到运行时的类         Class clazz1 = obj.getClass(); //获取到一个类         System.out.println(clazz1.getName());         Class clazz2 = Person.class;         System.out.println(clazz2.getName());         String className = "com.java.kudy.day17_2.reflectDemo.Person";         Class clazz3 = Class.forName(className);         System.out.println(clazz3.getName());         Class clazz4 = int.class;         System.out.println(clazz4.getName());  //我们已经映射出一个类                  //获取到一个类中所有的属性(成员属性-->字段)         Class clazz = Person.class;         Field[] fields = clazz.getDeclaredFields();                  //遍历,.获取每一个成员属性         for(Field field : fields)         {             /*              * 基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)              * 和关键字 void 也表示为 Class 对象-->所以我们返回它的父类的正确的              */             String name = field.getName(); //字段名             String type = field.getType().getName(); //类型             System.out.println("类型:"+type+"字段名:"+name);         } /*                 //获取一个obj对象name的属性,并且改变name属性的值         Field declareField = clazz.getDeclaredField("name"); //必须要知道一个字段的名字         declareField.setAccessible(true); //编译检查去掉-->private-->public         Object value = declareField.get(obj); //获取这个对象字段的值          System.out.println(value); //其实这个是打印了对象的toString方法         //如果底层字段的类型为基本类型,则对新值进行自动解包          declareField.set(obj,"kudy");  //异常信息:有可能底层是不能被访问的          Object oj = declareField.get(obj); //返回该字段的值,返回的是object 其实是String类型         System.out.println(oj.toString());*/                  /*          * 获取一个类中定义的所有方法          */         Method[] methods = clazz.getDeclaredMethods();         for(Method method : methods)         {             //1.获取到一个方法的名称             String name = method.getName();              //2.获取到一个方法的修饰符             System.out.print(name+"\t");             int num = method.getModifiers();             if(Modifier.isPublic(num))                 System.out.print("public\t");             if(Modifier.isPrivate(num))                 System.out.print("Private\t");             if(Modifier.isAbstract(num))                 System.out.print("abstractor\t");             //3.获取到形参类型             Class[] parameterTypes = method.getParameterTypes();             for(Class type : parameterTypes)                 System.out.print(type.getName()+"\t");              //4.获取到一个返回值类型             Class returnType = method.getReturnType();  //返回一个返回值类型  void             System.out.println(returnType.getName());             System.out.println();         }         /*          * 调用obj的setName方法将名字更改成王五          Method method =clazz.getDeclaredMethod("setName",String.class);         method.setAccessible(true);//去掉安全的检查         method.invoke(obj, "my_kudy");         System.out.println(obj.toString());          */                  //获得类中定义的构造方法         Constructor[] constructors = clazz.getDeclaredConstructors();         for(Constructor constructor : constructors)         {             String name = constructor.getName();             System.out.println("构造方法名为:"+name);             Class[] types  = constructor.getParameterTypes();             System.out.println("参数类型为:");             for(Class type : types)                 System.out.print(type.getName()+" ");             System.out.println();         }                  //调用有参的构造方法,创建对象         //Class cz  = String.class /*        Constructor constructor =                         clazz.getDeclaredConstructor(String.class,int.class);*/         //基本参数和引用参数都要进行方法调用转换。          Constructor constructor =             clazz.getDeclaredConstructor(new Class[]{String.class,int.class});         Person p =(Person)constructor.newInstance("小细",19);         System.out.println(p);                  //获得包名         Package pa = clazz.getPackage();         System.out.println(pa.getName());                  //获得该类或接口的修饰符         int mod = clazz.getModifiers();         if(Modifier.isPublic(mod))             System.out.println("public修饰");         if(Modifier.isAbstract(mod))             System.out.println("Abstractor修饰");     }  }

面向接口编程思想:

接口:

package com.java.kudy.day17_2.GraphDemo;  public interface GetGraph {              Double getArea();      } Round.class package com.java.kudy.day17_2.GraphDemo;  public class Round implements GetGraph{          private double r;     @Override     public Double getArea() {         return Math.PI*r*r;     }      }  Test类: package com.java.kudy.day17_2.GraphDemo;  import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Field;  public class Test {      /**      * @param args      * @throws IOException       * @throws ClassNotFoundException       * @throws IllegalAccessException       * @throws IllegalArgumentException       * @throws InstantiationException       */     public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalArgumentException, IllegalAccessException, InstantiationException     {         BufferedReader br = new              BufferedReader(new InputStreamReader(System.in));         System.out.println("请输入你需要实现的图形:");         String className = br.readLine();         //映射出一个圆         Class clazz =  null;         try         {             clazz = Class.forName("com.java.kudy.day17_2.GraphDemo."+className);          }catch(RuntimeException e)         {             System.out.println("您输入的功能还没有实现!!!,等待更新!!");             return ;         }         //获取到一个类.为这个类创建对象         //获取到的类是Round.class         GetGraph g = (GetGraph)clazz.newInstance(); //为这个类创建对象           //本来是一个Person类型的引用,现在是Object         //Object obj = new Person();         //GetGraph g = (GetGraph) Person(); //如果是继承关系.是可以把它更改一吧.         //接口指向实现接口         /*          * Object obj = new Round();          * (GetGraph)          * 接口--> = 实现接口           */         Field[] fields = clazz.getDeclaredFields();         //遍历所有的属性,并且为他赋值 field.getName()意思: 获取这个属性的名字         for(Field field :fields)         {             System.out.println("请输入"+field.getName());  //获取到这个属性的名字             String value = br.readLine();             field.setAccessible(true);//去掉安全检查             Double d = Double.parseDouble(value);                 field.setDouble(g, d);         }         double area = g.getArea();         System.out.println(area);     }  }

小小的案例回顾:


package com.java.kudy.day17_2.GraphDemo;  class A {     public void run()     {         System.out.println("A.running");     } }  class B extends A {     public void run()     {         System.out.println("B.running");     } }  class C extends B {     public void run()     {         System.out.println("C.running");     } } public class TestExtends {     /*      * 我父类型的引用指向子类型的对象      * 但是我们如果想拿第二个子类指向第一个父类.是不可以的.所以我们必须要把它所指向的类型更改为B      */     public static void main(String[]args)     {         A a = new C();         a.run();         B b =(B)a;         b.run();     } }   ------------用面向接口的思想实现一个长方形(要求用到反射.)  接口: package com.java.kudy.day17_2.CollectionTest;  public interface GetSRound {          //实现一个面积     double getArea(); }  实现长方形的方法: package com.java.kudy.day17_2.CollectionTest;  public class Square implements GetSRound{     private double broder ;      @Override     public double getArea() {         return broder*broder;     } }  Test: package com.java.kudy.day17_2.CollectionTest;  import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Field;  import com.java.kudy.day17_2.GraphDemo.GetGraph;  public class Test {      /**      * @param args      * 用反射求一个正方形的面积      * @throws IOException       * @throws ClassNotFoundException       * @throws IllegalAccessException       * @throws InstantiationException       */     public static void main(String[] args) throws IOException,                                          ClassNotFoundException,                                         InstantiationException,                                          IllegalAccessException      {          //字节流转换成字符流         BufferedReader br =                  new BufferedReader(new InputStreamReader(System.in));         System.out.println("请输入你要希望求的图形");         String className =  br.readLine(); //获取一个类         System.out.println(className);         Class clazz = null;         try         {             //获取一个类             //Class clazz = Square.class             clazz = Class.forName("com.java.kudy.day17_2.CollectionTest."+className);         }catch (RuntimeException e) {             System.out.println("该功能还没有实现.程序已经退出..");             return;         }         //为这个类创建对象         GetSRound g = (GetSRound)clazz.newInstance();  //接口指向实现接口.由于接口里面的方法已经被实现.所以调用她其实就是调用实现接口里面的方法         Field[] fields = clazz.getDeclaredFields(); //遍历成员变量         for(Field field : fields)         {             //遍历所有的成员变量,为属性赋值             System.out.println("请输入:"+field.getName()); //获取成员变量名             field.setAccessible(true); //去掉私有的检查,因为这个类是私有的就oh啦             String str = br.readLine();             Double value = Double.parseDouble(str);             field.setDouble(g, value);         }         double area = g.getArea();         System.out.println(area);     }  }