黑马程序员-学习日记22(java高新技术2)

来源:互联网 发布:iphone4 ios7越狱优化 编辑:程序博客网 时间:2024/05/19 23:11

-------android培训java培训、期待与您交流! ----------

 

21.成员变量反射的综合案例

 需求:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a".
22.成员方法的反射

 1.Method类
  1)Method类代表某个类中的一个成员方法
  2)得到类中的某一个方法:
  例子:Method charAt = Class.forName("java.lang.String").getMethod("charAt",int.class);
  3)调用方法:
  <1>通常方式:System.out.println(str.charAt(1));
  <2>反射方式:System.out.println(charAt.invoke(str,1));
  注:如果传递给Method对象的invoke()方法的一个参数为null,说明该Method对象对应的是一个静态方法。
 2.JDK1.4和JDK1.5的invoke方法的区别:
    <1>jdk1.5:public Object invoke(Object obj,Object...args)
    <2>jdk1.4:public Object invoke(Object obj,Object[]args),即按jdk1.4的语法,需要将
    一个数组作为参数传递给invoke方法时,数组中的每个元素分别对应被调用方法中的一个参
    数,所以调用charAt方法的代码也可以用jdk1.4改写为charAt.invoke("str",new Object[]{1})形式。
    <3>jdk1.4:new String[]{new String("abc"),2}---->new Object[]{2};
 3.代码演示:见ReflectTest.java

23.对接收数组参数的成员方法进行反射

 1.用反射方式执行某个类中的main方法
  1)需求:
  写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法
  (用普通方式调完后,要明白为什么要用反射方式去调用?)
  2)问题:
  启动java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),
  通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,
  整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,因为jdk1.5
  要兼容jdk1.4的语法,所以当把一个字符数组作为参数传递给invoke方法时,javac会按jdk1.4
  的语法进行处理。不能使用代码:mainMethod.invoke(null,new String[]{"xxx"});
  3)解决办法:
  <1>mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});//即封装成一个参数
  <2>mainMethod.invoke(null,(Object)new String[]{"xxx"});//这样做等于告诉编译器说这是一个参数
                  //编译器就不分把参数当数组看待,也不会把数组打散成若干个参数了.
 2.eclipse使用技巧---main参数设置
  选中类名--->F2显示完整类名--->复制类名--->右键-->Run As-->Run Configurations--->打开Arguments面板
  --->在Promgram arguments区域中粘贴刚才复制的完整类名。
 
 
 3.代码演示:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectTest {
 public static void main(String[] args)throws Exception
 {
  //TestArguments.main(new String[]{"111","222","333"});
  String startingClassName = args[0];
  Method mainMethod = Class.forName(startingClassName).getMethod("main",String[].class);
  //mainMethod.invoke(null,new Object[]{new String[]{"111","222","333"}});
  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);
  }
  
 }
}

24.数组与Object的关系及其反射类型

 1.数组的反射
  1)具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
  2)代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class.
  3)基本类型的一维数组可以被告当作Object类型使用,不能当作Object[]类型使用,
  非基本类型的一维数组,即可以当作Object类型使用,也能当作Object[]类型使用。
  4)Arrays.asList()方法处理int[]和String[]时的差异。
  5)Arrays工具类用于完成对数组的反射操作。
  6)问题:怎么得到数组中的元素类型?
 2.Arrays工具类中的asList方法(将数组转换成List):
  public static <T> List<T> asList(T... a)返回一个受指定数组支持的固定大小的列表。
 3.代码演示:
  
  int[] a1 = new int[]{1,2,3};
  int[] a2 = new int[4];
  int[][] a3 = new int[2][3];
  String[] a4 = new String[]{"a","b","c"};
  System.out.println(a1.getClass() == a2.getClass());
  System.out.println(a1.getClass == a4.getClass());
  System.out.println(a1.getClass() == a3.getClass());
  System.out.println(a1.getClass().getName());
  System.out.println(a1.getClass().getSuperclass().getName());//获取Class实例对象的父类对应的Class实例对象名称为Object
  System.out.println(a4.getClass().getSuperclass().getName());
  
  Object aobj1 = a1;
  Object aobj2 = a4;
  //Object[] aobj3 = a1;
  Object[] aobj4 = a3;
  Object[] aobj5 = a4;
  
  System.out.println(a1);
  System.out.println(a4);
  System.out.println(Arrays.asList(a1));//--->a1整体相当于一个Object类型,故打印结果为一个对象的哈希值。
  System.out.println(Arrays.asList(a4));//--->a4中相当于有三个Object类型,故打印结果为[a,b,c].

25.数组的反射应用

 1.类 Array(java.lang.reflect)
  1)public final class Array
     extends Object
  Array 类提供了动态创建和访问 Java 数组的方法。 Array 允许在执行 get 或 set 操作期间进行扩展转换,
  但如果发生收缩转换,则抛出 IllegalArgumentException。
  2)方法摘要
  static Object get(Object array, int index)
    返回指定数组对象中索引组件的值。
  static int getLength(Object array)
    以 int 形式返回指定数组对象的长度。
  static void set(Object array, int index, Object value)
    将指定数组对象中索引组件的值设置为指定的新值。  
 2.问题:怎么得到数组的元素类型?
  int[] a = new int[3];
  Object[] a = new Object[]{"a",1};
  因为数组中的对象类型是不确定的,所以没办法得到数组的元素类型。
  而只能得到某一个具体元素的类型。如:a[0].getClass().getName();
26.ArrayList_HashSet的比较及Hashcode分析

 1.ArrayList与HashSet区别
  ArrayList是有顺序的集合,HashSet是要通过比较哈希值,存入不同哈希值对象数据的集合。
 2.eclipse使用技巧---设置hashCode和equals方法
  右键-->Source--->Generate hashCode() and equals()--->勾选x,y
 3.hashCode()方法的作用:
  要查找集合中的某个对象,通常是逐一查找,当发现某个元素与要查找的对象进行equals方法比较
  的结果相等时,就停止查找。此时若集合中元素过多,则查找效率十分低下。而哈希算法可提高查
  找元素的效率,这种方式将集合分成若干个存储区域,每个对象可计算出一个哈希码,将哈希码分组,
  每组分别对应某个存储区域,根据一个对象的哈希码就可以确定该对象存储在哪个区域。

  HashSet就是采用哈希算法存取对象的集合,Object类中定义了一个hashCode()方法来返回每个java对象
  的哈希码,当从HashSet集合中查找某个对象时,java系统首先调用对象的hashCode()方法获得该对象
  的哈希码,然后根据哈希码找到相应的存储区域,最后取出该存储区域内的每个元素与该对象进行
  equals方法比较,这样不用遍历集合中的所有元素就可以得到结论,hashCode()使HashSet集合具有
  很好的对象检索性能,极大提高了存储对象的效率。

  为保证一个类的实例对象在HashSet中正常存储,则要求这个类的两个实例对象用equals()方法比较结果
  相等时,它们的哈希码也必须相等。否则一个类的两个实例对象用equals()方法比较相等时,仍会被存
  到Set集合中。Object类中的hashCode()方法不能满足对象被存入到HashSet中的要求,因为它的返回值
  是通过对象的内存地址推算出来的,同一个对象在程序运行期间的任何时候返回的哈希值都是始终不变的。
  所以两个不同的实例对象,即使它们的equals方法比较相等,它们默认的hashCode()返回值是不同的。

  只有类的实例对象要被采用哈希算法进行存储和检索时,这个类才需要按要求覆盖hashCode方法,通常要求
  hashCode方法和equals方法一并被同时覆盖。

  注:
  通常一个类的两个实例对象equals()比较相等时,哈希值也必相等。但equsals()比较不相等的两相对象
  可以有相同的哈希码。如:“BB”与“Aa”,equals()比较不相等,但它们的hashCode()返回值却相等。
 4.内存泄露;
  当一个对象被存储到HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值
  的字段了,否则,对象修改后哈希值就变了,这种情况下,使用contains方法传入该对象当前
  引用作为参数无法检索到对象,这也导致无法从HashSet集合中单独删除当前对象,从而造成
  内存泄露。
27.框架的概念及用反射技术开发框架的原理

 1.反射的作用-->实现框架功能
  1)框架与框架要解决的核心问题
  <1>我做房子给用户住,用户自己安装门窗,我做的房子就是框架,用户需要使用我的框架,
    把门窗插入进我提供的框架中,框架与工具类有区别,工具类被用户的类调用,而框架
    则是调用用户提供的类。
  <2>你做的门调用锁,锁是工具,你做的门被房子调用,房子是框架,房子和锁都是别人提供的。
  2)框架要解决的核心问题:
  <1>若干年前写的框架可以调用若干年后写的程序。
  <2>写程序时无法知被调用的类名,所以在程序中无法直接new某个类的实例对象,
   而要用反射来做。

 2.在eclipse中的代码演示:
  创建配置文件:工程上右键-->New -->File-->config.properties-->输入:className=java.util.ArrayList
28.用类加载器的方式管理资源和配置文件

 1.(类 ClassLoaderjava.lang )
  1)public abstract class ClassLoaderextends Object类加载器是负责加载类的对象。
  ClassLoader 类是一个抽象类。如果给定类的二进制名称,那么类加载器会试图查找或生成构成类定义的数据。
  一般策略是将名称转换为某个文件名,然后从文件系统读取该名称的“类文件”。

 每个 Class 对象都包含一个对定义它的 ClassLoader 的引用。
  2)方法摘要
   InputStream getResourceAsStream(String name)
          返回读取指定资源的输入流。

 2.将文件放到源文件下,会自动将它的字节码文件搬到classPath目录下。如:将config.properties放在包cn.itcast.day1下
   未来学到的框架的配置文件都是放在classPath指定的目录下,因为它内部用的是类加载配置文件。
   和包有关系,用相对路径,和包没关系,用绝对路径(前加/),无论是相对还是绝对,内部都是用classLoader
 3.代码分析:
  InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");
  //此例运行是将配置文件放在了源文件(src)目录下,意为:从根目录下开始查找,若不加cn/itcast/day1的话就找不到文件。
  InputStream ips = ReflectTest2.class.getResourceAsStream("resources/config.properties");
  //此例运行是将配置文件放在了源文件的新建包cn.itcast.day1.resources下,意为:从默认的程序路径下开始查找,即从包cn.itcast.day下找。(相对路径)
  InputStream ips = ReflectTest2.class.getResourceAsStream("/cn/itcast/day1/resources/config.properties");
  //加/代表从根目录下开始找(绝对路径)
29.由内省引出JavaBean的讲解

 1.内省对应的英文单词是IntroSpector,它主要用于对JavaBean进行操作。
 2.了解JavaBean
  1)JavaBean是一种特殊的java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的
  字段,且方法名符合某种命名规则。
  2)如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象
     通常称之为值对象(Value Object,简称VO)。这些信息在类中用私有字段来存储,用set()和get()
  方法来设置和获取。
  3)通过提供的set和get方法就知道属性名,一个类被当作JavaBean使用时,JavaBean的属性是根据方法名
  推断出来的,它根本看不到java类内部的成员变量。
  如果第二个字母是小写的,则把第一个字母变成小写的:
  gettime-->time
  setTime-->time
  getCPU-->CPU

  4)一个符合JavaBean特点的类可以当作普通类进行使用,但当作JavaBean用会有额外的好处。
30.对JavaBean的简单内省操作

 1.eclipse使用技巧
  1)生成get和set方法
     右键-->Source-->Generate Getters and Setters -->勾选x,y -->OK
  2)抽取方法:
  选中代码-->右键-->Refactor-->Extract Method -->输入方法名:eg:getProperty
 2.PropertyDescriptor(java.beans 包)属性描述类
  1)public class PropertyDescriptor
      extends FeatureDescriptor
     PropertyDescriptor 描述 Java Bean 通过一对存储器方法导出的一个属性。
  2)构造方法摘要
  PropertyDescriptor(String propertyName, Class<?> beanClass)
          通过调用 getFoo 和 setFoo 存取方法,为符合标准 Java 约定的属性构造一个 PropertyDescriptor。
  PropertyDescriptor(String propertyName, Class<?> beanClass, String readMethodName, String writeMethodName)
          此构造方法带有一个简单属性的名称和用于读写属性的方法名称。
  PropertyDescriptor(String propertyName, Method readMethod, Method writeMethod)
          此构造方法带有某一简单属性的名称,以及用来读取和写入属性的 Method 对象。
  3)方法摘要
   Class<?> getPropertyType()
   获得属性的 Class 对象。
  Method getReadMethod()
   获得应该用于读取属性值的方法。
  Method getWriteMethod()
   获得应该用于写入属性值的方法。
   void setReadMethod(Method readMethod)
   设置应该用于读取属性值的方法。
  void setWriteMethod(Method writeMethod)
   设置应该用于写入属性值的方法。


 3.类 FeatureDescriptor(java.beans包)
  1)public class FeatureDescriptor
        extends Object
  FeatureDescriptor 类是 PropertyDescriptor、EventSetDescriptor 和 MethodDescriptor 等的公共基类。

  它支持一些可以设置和检索任意的内省描述符的公共信息。

  此外,它还提供了一种扩展机制,从而任意属性/值对都可以与设计特性相关联。
  2)构造方法摘要
  FeatureDescriptor()
   构造一个 FeatureDescriptor。
  3)方法摘要
   String getName()
          获得此特性的编程名称。
   Object getValue(String attributeName)
          利用此特性检索指定属性。
  void setName(String name)
          设置此特性的编程名称。
   void setValue(String attributeName, Object value)
          将某一指定属性与此特性相关联。

 

 

以下是我的程序代码:

 

import java.lang.reflect.*;
import java.util.Arrays;
import java.util.*;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Demo1Exercise1{
 public static void main(String args[])throws Exception{
  //getStrClass();
  //getPrimitive();
  getConstructor();
 }
 //得到字节码文件对象有三种方式:通过下列方法完成。
 public static void getStrClass()throws Exception{
  String str1 = "abc";
  Class cla1 = str1.getClass();
  Class cla2 = String.class;
  Class cla3 = Class.forName("java.lang.String");
  System.out.println((cla1 == cla2)+" "+(cla1 == cla3) +" "+(cla2 == cla3));
 }
 //打印字节码文件对象是不是原始类型,一共有九种原始类型。八个基本类型和一个void 类型,原始类型没有类加载器。
 public static void getPrimitive()throws Exception{
  System.out.println(void.class+"\t"+void.class.isPrimitive());
  System.out.println(int.class+"\t"+int.class.isPrimitive());
  //判断int型和Integer型的字节码是否相同。 
  System.out.println(int.class == Integer.class);
  //Integer(包装类)里面专门定义了一个常量TYPE,该常量表,包装类
  //里所包装的基本类型的字节码
  System.out.println(int.class+" = "+(int.class == Integer.TYPE)+" "+Integer.TYPE);
  //判断一个字节码文件对象是不是一个数组,用isArray();
  System.out.println("字节码文件对象是不是一个数组\t"+(int[].class.isArray()));
  //getComponentType()返回表示数组组件类型的 Class。如果此类不表示数组类,则此方法返回 null。
  int i = 5;
  System.out.println(int.class.getComponentType());
  System.out.println(int[][].class.getComponentType());
  System.out.println(int[][][].class.getComponentType());
 }
 //通过String字节码文件对象中的这个构造方法创建String对象:String(char[] value, int offset, int count) ;
 public static void getConstructor()throws Exception{
  Constructor<String> constructor1 = String.class.getConstructor(char[].class,int.class,int.class);
  char[] c = {'a','b','c'};
  String  str1 = constructor1.newInstance(c,0,2);
  System.out.println(str1);
 }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//   Field 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Point1{
 public int x;
 private int y ;
 public Point1(int x,int y){
  this.x = x;
  this.y = y;
 }
 public void setX(int x){
  this.x = x;
 }
 public int getX(){
  return this.x; 
 }
 public void setY(int y){
  this.y = y;
 }
 public int getY(){
  return this.y;
 }
 public int hashCode(){
  final int prime = 31;
  return prime*x+y;
 }
 public boolean equals(Object o){
  if(this == o)
   return true;
  if(this.getClass() != o.getClass())
   return false;
  final Point1 p = (Point1)o;
  return this.x == p.x && this.y == p.y;
 }
 public String toString(){
  return x+"::"+y;
 }
}
class Demo1Exercise2{
 public static void main(String args[])throws Exception{
  Point1 p = new Point1(5,10);
  Field fieldx = p.getClass().getField("x");
  Object x = fieldx.get(p);
  System.out.println(x);

  Field fieldy = p.getClass().getDeclaredField("y");
  fieldy.setAccessible(true);
  Object y = fieldy.get(p);
  System.out.println(y);
 }
}
class Point2{
 public String x;
 private String y ;
 public String w = "aaabbbcccddd";
 public int w1 = 11;
 public String ww = "acccdddaaaaaa";
 public Point2(String x,String y){
  this.x = x;
  this.y = y;
 }
}

//将任意一个对象中的所有String类型的成员变量所对应的字符串
//内容中的“b”改成“a”;
class Demo1Exercise3{
 public static void main(String args[])throws Exception{
  Point2 p = new Point2("abc","cba");
  Field[] fields = p.getClass().getFields();
  for(int x=0;x<fields.length;x++){
   String o = ((String)fields[x].get(p)).replace('a','x');
   fields[x].set(p,o);
   System.out.println(fields[x].get(p));
  }
 }
}

class Demo1Exercise4{
 public static void main(String args[])throws Exception{
  Point2 p = new Point2("aba","cba");
  Field[] fields = p.getClass().getDeclaredFields();
  for(int x=0;x<fields.length;x++){
   if(fields[x].getType() == String.class){
    fields[x].setAccessible(true);
    String o = ((String)fields[x].get(p)).replace('a','x');
    fields[x].set(p,o);
    System.out.println(fields[x].get(p));
   }
  }
 }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//   Method  调用指定的Method方法。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

class Demo1Exercise5{
 public static void main(String args[])throws Exception{
  String str = "abcdef";
  Method method = String.class.getMethod("concat",String.class);
  System.out.println(method.invoke(str,"aaaaaaaa"));
 }
}


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

//一般的方法来调用主函数 。
class Demo1Exercise7{
 public static void main(String args[])throws Exception{
  Demo1Exercise6.main(new String[]{"111","222","333"});
 }
}

 

class Demo1Exercise8{
 public static void main(String args[])throws Exception{
  String str = args[0];
  Method method1 = Class.forName(str).getMethod("main",String[].class);
  //该方法为静态的,用str,或null调用都是一样的。
  Object o = method1.invoke(str,(Object)new String[]{"333","222","111"});
  //为何返回的是null;
  System.out.println(o);
  //method1.invoke(str,(Object)new String[]("333","222","111"));
 }
}


//每一个具有相同数据类型和维数的数组,它们用的是同一个字节码文件。

class Demo1Exercise9{
 public static void main(String args[])throws Exception{
  int[] i1 = new int[3];
  int[] i2 = new int[4];
  int[][] i3 = new int[2][2];
  String[][] i4 = new String[4][];
  System.out.println(i1.getClass() == i2.getClass());
  //因为a1和a4都是一维数组类型,它们的父类都是Object所以可用Object接收。
  Object aobj1 = i1;
  Object aobj2 = i4;
  //基本数据类型的数组是不能转换成Object[]数组的。因为基本类型不是类。
  //Object[] aobj3 = i1;
  Object[] aobj4 = i3;
  Object[] aobj5 = i4;
 }
}

class Demo1Exercise10{
 public static void main(String args[])throws Exception{
  //java中如果在后面指定了值,在前面就不能在指定个数了。
  int[] a1 = new int[]{1,2,3};
  int[] a2 = new int[4];
  int[][] a3 = new int[2][3];
  String[] a4 = new String[]{"a","b","c"};//class or interface Lclassname
  System.out.println(a1.getClass() == a2.getClass());
  System.out.println("====JDK1.4=====jDK1.5===");
  System.out.println(a1);
  System.out.println(a4);
  System.out.println(Arrays.asList(a1));
  System.out.println(Arrays.asList(a4));
 }
}

 


class Demo1Exercise11{
 public static void main(String args[])throws Exception{
  //java中如果在后面指定了值,在前面就不能在指定个数了。
  int[] a1 = new int[]{1,2,3};
  String[] a4 = new String[]{"a","b","c"};//class or interface Lclassname
  printObject(a4);
  printObject(a1);
  printObject("xyz");
  System.out.println(a1.getClass().getSuperclass().getName());
  System.out.println(void.class.getSuperclass().getName());
 }
 public static void printObject(Object obj){
  Class clazz = obj.getClass();
  //判断该字节码文件对象是否是一个数组类。
  if(clazz.isArray()){
   // 以 int 形式返回指定数组对象的长度。
   int len = Array.getLength(obj);
   for(int i=0;i<len;i++){
    //返回指定数组对象中索引组件的值,返回的是Object.
    System.out.println(Array.get(obj,i));
   }
  }else{
    System.out.println(obj);
  }
 }
}

 

 

class Demo1Exercise12{
 public static void main(String args[])throws Exception{
  System.out.println(void.class.getSuperclass().getName());
  System.out.println(Object.class.getSuperclass().getName());
 }
}
  

 

class Demo1Exercise13{
 public static void main(String args[]){
  ArrayList<Person> a1 = new ArrayList<Person>();
  a1.add(new Person("abc1"));
  a1.add(new Person("abc2"));
  a1.add(new Person("abc3"));
  printColl(a1);
  ArrayList<Student> a11 = new ArrayList<Student>();
  a11.add(new Student("abc--1"));
  a11.add(new Student("abc--2"));
  a11.add(new Student("abc--3"));
  printColl(a11);
  
 }
 public static void printColl(ArrayList<? super Student> a1){//ArrayList<String> a1 = new ArrayList<Student>();
  Iterator<? super Student> it = a1.iterator();
  while(it.hasNext()){
   System.out.println(((Person)it.next()).getName());
  }
 }
}
class Person{
 private String name;
 Person(String name){
  this.name = name;
 }
 public String getName(){
  return name;
 }
}
class Student extends Person{
 public Student(String name){
  super(name);
 }
}

 

class Demo1Exercise14{
 public static void main(String args[]){
  int[] i = new int[]{1,2,3};
  String s = "wfygyiq";
  print(i);
  print(s);
 }
 public static void print(Object o){
  Class clazz = o.getClass();
  if(clazz.isArray()){
   int len = Array.getLength(o);
   for(int x=0;x<len;x++){
    System.out.println(Array.get(o,x));
   }
  }else{
   System.out.println(o);
  }
 }
}

//内存泄露了。。。。。。。。。。。。
class Demo1Exercise15{
 public static void main(String args[]){
  Point1 p1 = new Point1(11,22);
  Point1 p2 = new Point1(11,33);
  Point1 p3 = new Point1(11,44);
  Point1 p4 = new Point1(11,22);
  Collection<Point1> hs = new HashSet<Point1>();
  hs.add(p1);
  hs.add(p2);
  hs.add(p3);
  hs.add(p4);//hashSet中它没有存进来。
  System.out.println(hs);
  //p1.setY(88);
  hs.remove(p1);
  System.out.println(hs);
 }
}

 

class Demo1Exercise16{
 public static void main(String args[]){
  Point1 p1 = new Point1(11,22);
  Point1 p2 = new Point1(11,33);
  Point1 p3 = new Point1(11,44);
  Point1 p4 = new Point1(11,22);//ArrayList中它进行存储进来。
  Collection<Point1> hs = new ArrayList<Point1>();
  hs.add(p1);
  hs.add(p2);
  hs.add(p3);
  hs.add(p4);//hashSet中它没有存进来。
  System.out.println(hs);
  p1.setY(88);//ArrayList中因为采用的是数组结构,并不需计算hashCode值,所以能删除了。
  hs.remove(p1);
  System.out.println(hs);
 }
}

 

//通过Properties类和反射来写上例;
class Demo1Exercise17{
 public static void main(String args[])throws Exception{
  FileInputStream f = new FileInputStream("11.txt");
  Properties p = new Properties();
  p.load(f);
  String str = p.getProperty("className");
  f.close();
  Collection c = (Collection)Class.forName(str).newInstance();
  Point1 p1 = new Point1(11,22);
  Point1 p2 = new Point1(11,33);
  Point1 p3 = new Point1(11,44);
  Point1 p4 = new Point1(11,22);//ArrayList中它进行存储进来。
  c.add(p1);
  c.add(p2);
  c.add(p3);
  c.add(p4);
  System.out.println(c);


 }
}


//思考题:怎么得到数组中的元素类型。   怎么得到数组的类型。
// 答:先得到数组中的一个元素,然后得到它的字节码对象,再调用getName()方法。
class Demo1Exercise18{
 public static void main(String args[])throws Exception{
  Object[] o = new Object[]{"abc",1111,'c'};
  System.out.println("\t\t\t"+o.getClass().getComponentType());
  String[] o1 = {"33","2","v"};
  print(o1);
  //如果此 Class 表示 Object 类、一个接口、一个基本类型或 void,则返回 null。
  System.out.println(void.class.getSuperclass());
 }
 public static void print(Object o){
  Class clazz = o.getClass();
  if(clazz.isArray()){
   int len = Array.getLength(o);
   for(int i=0;i<len;i++){
    System.out.println(Array.get(o,i).getClass().getName());
   }
  }
 }
}

 

 

原创粉丝点击