`
_kudy
  • 浏览: 15090 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

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

阅读更多

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);
     }
 
 }

  

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics