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

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

 

.JDK1.5和JDK1.6的新特性?

         JDK1.5
      1.静态导入
      2.可变参数
      3.增强的for循环
      4.基本数据类型的自动拆箱与装箱
      5.枚举
      6.注解
      7.泛型

 见:F:\lx\heima\java知识集
02.eclipse及IDE开发工具介绍

   1.MyEclipse是Eclipse的一个插件,将MyExclipse和eclipse打包作为开发javaEE的工具,
   即为扩展的MyExclipse开发工具。eclipse是由java编出来的IDE开发工具。
   2.启动java中的图形界面所用的虚拟机通常启动的是javaw.exe。因为javaw.exe启动时会关掉
   命令行窗口。若eclipse关不了了,可以通过关闭任务管理器中的javaw.exe来完成关闭。
   3.一些述语的简写:
   sun公司:Stanford University Network斯坦福大学网络公司
   JDK:Java Development Kit(软件开发包)
   JVM:Java Virtual Machine (java虚拟机)
   java ee:Java(2platform) Enterprise Edition  JAVA企业版
   JRE:Java Runtime Environment(java 运行环境)
   ide:itegrity development environment集成开发环境
   jms
   jmx
   jndi
   OOP  object oriented programming 面向对象编程
   4.另一个开发java的IDE是:NetBeans
 NetBeans也是一个免费的开源的由sun公司开发的IDE工具。
 由于大家习惯了使用eclipse,所以NetBeans很难推广起来。

 5.还有一个java的IDE开发环境:JBuider
 因为是收费的,所以几乎被淘汰。

03.eclipse工程管理与快捷键配置

 1.IDE开发工具都支持使用工程化方式管理一个项目的程序开发过程,一般来说一个相对独立的项目就是一个工程,
 一个项目中涉及的多个java文件,资源文件(配置文件)等用一个工程进行管理。使用工程管理,开发工具能对
 所有源文件集中管理,记住每个源文件的位置和相互关系。工程中有哪几个源文件、启动类是哪个、启动参数设置
 等配置信息在工程中都有记录。
 2.一个workspace可以包含多个project,一个workspace保留了eclipse的一套环境选项的配置,例如,所使用的
 javac和java命令,等等,如果要为eclipse再配置一套环境选项,可以再创建一个workspace。package explore
 视图窗口中的filters菜单项,可以显示空的父包(该功能默认是关闭的)
 3.配置版本:
 windows-->preferences-->java--> compiler(编译版本设置)
         Installed JREs(运行版本设置)
 4.新建工作间:
 File-->SwitchWorkspace(切换工作间)-->other-->输入新工作间的名称如:E\workspace4--->OK

 5.新建一个工程:
 File-->New-->Project-->选择JavaProject(普通java工程)-->Next-->Project name:staticimport-->Finish
 -->提示是否切换到透视图下(perspective)-->yes
 6.新建一个类:
 在Projcet上右击-->New-->class-->Package:cn.itcast.day1
         Name : StaticImport

 7.更改工程名:
 在工程上右击-->Refactor(重构)-->Rename-->New name:javaenhance(加强之意)
 8.快捷键配置:
 Window-->Preferences-->General(通用)-->keys-->输入content a-->在显示列中找到Content Assist(内容协助)
 -->设置其快捷键如:Alt+/(若想解除快捷键设置的绑定关系,按Unbind Command即可)-->Apply(应用)-->OK

 注:此处配置的是:System.out.println()这句的快捷键.
  快捷键的设置位置在:General-->keys
  代码模块的设置位置在:java-->editor-->Templates

04.eclipse视图管理与程序调试

 1.Perspective与view的区别:
 一个透视图是若干个小视图的集合。如:java透视图,Debug透视图等。
 2.Debug透视图下调试变量
 制作调试端点(在要调试的变量行前双击)-->切换到Debug透视图-->选中变量x并右击-->Watch(此时可以看到变量的值)
 -->点击下一步的图形箭头进行一步步的调试(调试时观察变量值的变化)
 3.如何调出视图:
 Window-->Show View-->点选要打开的视图(如:outline)-->若找不到时,可到other中去找。

05.配置eclipse编译与运行环境

 1.设置整个workspace的javac与java
 windows-->preferences-->java--> compiler(编译版本设置)
         Installed JREs(运行版本设置)
 2.设置单个工程的javac与java
  设置javac:选择工程-->右键-->Properties-->Java Compiler-->设置编译版本
  设置java:选择工程-->右键-->run as-->Run Configurations (老版本是:open run dialog)
     -->JRE-->Installed JREs-->Add-->Standard VM-->Next-->Directory选择jdk的版本目录-->设置运行彼本
 3.注意:
  1)高版本的java能运行低版权本的javac编译的程序,
  低版本的java不能运行高版本的javac编译的程序。
  2)eclipse工作台中的所有工程继承工作台的配置,其中某个工程也可以覆盖工作台的配置。

06.在eclipse中配置java模版代码

 1.代码模板的运用:
 选择代码-->右键-->Surround With-->选择模板如:Try/Catch Block
 2.代码模版的设置:如:设置一个try{}finally{}的模板
 Window-->Preferences-->java-->Editor-->Templates-->New-->Name:tryf
               Pattern:try{
                  
                  }finally{
                  
                  }
             
     --->Insert Variable(设置{}中的主体内容)-->line_selection(为原来的内容)
                 -->cursor(光标的位置)

         
07.在eclipse中导入已有的工程

 1.将工程导入工作台
  1)切换工作间到workspace2:File-->SwitchWorkspace-->workspace2.
  2)将workspace1中的javaenhance工程拷贝到workspace2的目录下.
  3)File-->Import-->General-->点选Existing Projects into Workspace(存在的工程)-->Next-->
     按Browse选择根目录。Select root directory:E:\workspace2\javaenhance --->Finish
 2.工作台环境不同的话,要重新配置JRE库
  注:JRE环境即JRE System Library,该库中包含许多JRE的jar包。
  1)删除库:在工程上右击-->Build Path-->Configure Build Path-->按Remove删除已有的JDK的库
  2)增加库:在工程上右击-->Build Path-->Configure Build Path-->按Add Library(增加库)
    ---><1>选择JRE System Library(增加JRE的库)-->Next-->选择jre的库Workspace default JRE(Sun JDK1.6.0_13)-->Finish
     <2>选择MyExclipse Libraries(增加MyEclipse插件带的库)
     <3>选择User Library(增加新的库)-->Next-->User library name:xxx(例)
      -->Add JARs(在该库下可任意增加许多jar包)
     
08.java5的静态导入与编译器语法设置

 1.import与import static语句的区别:
   import语句可以导入一个类或某个包中的所有类
   import static 语句导入一个类中的某个静态方法或所有静态方法。
 2.语法举例
   求两个数的最大值和相减结果的绝对值:
   System.out.println(Math.max(3,9));//此时的Math类可省略。
   System.out.println(abs(3-9));
   此例的静态导入是:import static java.lang.Math.*;

   注:若将javac无意改成了1.4,则静态导入等JDK1.5的特性都会报错.

09.可变参数与OverLoad相关面试题分析

 1.可变参数
  1)问题:一个方法接受的参数个数不固定,例如:
   System.out.println(add(2,3,5));
   System.out.println(add(1,2,3,5));
  2)可变参数的特点:
  <1>只能出现在参数列表的最后;
  <2>...位于变量类型和变量名之间,前后有无空格都可以;
  <3>调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,
     在方法体中以数组的形式访问可变参数。
  3)代码见cn.itcast.day1.VarableParameter.java

 2.说一说overload(重载)与override(重写)的区别?

10.java5的增强for循环

 1.增强for循环
  1)语法:for(type 变量名:集合变量名){...}
  2)注意事项:
   迭代变量必须在()中定义!
   集合变量可以是数组或实现了Iterable接口的集合类。
  3)举例:
  public static int add(int x,int ... args)
  {
   int sum = x;
   for(int arg : args)
   {
    sum += arg;
   }
   return sum;
  }

  4)注:注释的快捷键是:ctrl+shift+/
 2.系统学习知识的方法:查找知识的源头

  下载java的语言规范:langspec-3.0

11.基本数据的自动拆装箱及享元设计模式

 1.基本数据类型的自动拆箱与装箱
  1)自动装箱:
   Integer num1 = 12;
  2)自动拆箱:
   System.out.println(num1 + 12);
  3)基本数据类型的对象缓存:
  Integer num1 = 12;
  Integer num2 = 12;
  System.out.println(num1 == num2);

  Integer num3 = 129;
  Integer num4 = 129;
  System.out.println(num3 == num4);

  Integer num5 = Integer.valueOf(12);
  Integer num6 = Integer.valueOf(12);
  System.out.println(num5 == num6);
 2.JDK1.4以前的版本基本数据封装对象:Integer a = new Integer(3);//装箱
   JDK1.5以后基本数据的封装对象:Integer a = 3;//自动装箱
   在一字节内的整数(-128~127)由于使用频率高,在封装成对象时,就缓存起来了。
   以便复用,这种模式叫享元模式。
 3.享元设计模式(flyweight):
   如果很多很小的对象,它们有很多相同的东西,那就可以把它们变成一个对象,
   还有些不同的东西,可将它们变成外部的属性作为方法的参数传入。这种模式叫
   享元模式。
   eg:i.display(int x,int y)
   i(char,x,y)
 4.演示见AutoBox.java

12.枚举的作用介绍
 
 1.为什么要有枚举
  1)问题:要定义星期几或性别的变量,该怎么定义?假设用1-7分别表示星期一到星期日,但有人可能
     会写成 int weekday = 0;
  2)枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。
  枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。

  WeekDay weekDay = 7;定义一个新类型,用该类型定义的值只能是一个提前规定好的值,否则编译就不能通过。
 2.用普通类如何实现枚举功能,定义一个Weekday的类来模拟枚举功能。
  1)私有的构造方法。
  2)每个元素分别用一个公有的静态成员变量表示。
  3)可以有若干公有方法或抽象方法,例如,要提供nextDay方法必须是抽象的。
  采用抽象方法定义nextDay就将大量的if.else语句转移成了一个个独立的类。
 3.枚举的基本应用
  1)举例:定义一个WeekDay的枚举。
  2)扩展:枚举类的values,valueOf,name,toString,ordinal等方法
  3)总结:枚举是一种特殊的类,其中的每个元素都是该类的一个实例对象,例如可以调用
  WeekDay.SUN,getClass().getName和WeekDay.class.getName().

13.用普通类模拟枚举的实现原理

 1,为更好地理解枚举,若用普通类来模仿一下枚举,可参照java.awt.Color类。
  采用抽象方法定义nextDay就将大量的if.else语句转移成了一个个独立的类。
  如果想在一个类中编写完各个枚举类和测试调用类,那么可以将枚举类定义成调用类的内部类。
 2.在代码上创建类
   代码如:WeekDay weekDay = 7;
   操作:选中WeekDay-->Create class 'WeekDay'-->Finish
 3.演示如:EnumTest.java,WeekDay.java

14.java5的枚举的基本应用。

 public class EnumTest
 {
  public static void main(String[] args)
  {
   WeekDay weekDay2 = WeekDay.FRI;
   System.out.println(weekDay2);
   System.out.println(weekDay2.name());
   System.out.println(weekDay2.ordinal());
   System.out.println(WeekDay.valueOf("SAT"));
   System.out.println(WeekDay.values().length);
  }
 
  public enum WeekDay
  {
   SUN,MON,TUE,WEd,THI,FRI,SAT;
  }
 }

15.实现带有构造方法的枚举

 public class EnumTest
 {
  public static void main(String[] args)
  {
   WeekDay weekDay2 = WeekDay.FRI;
   System.out.println(weekDay2);
   System.out.println(weekDay2.name());
   System.out.println(weekDay2.ordinal());
   System.out.println(WeekDay.valueOf("SAT"));
   System.out.println(WeekDay.values().length);
  }
 
  public enum WeekDay
  {
   SUN,MON,TUE,WEd,THI,FRI,SAT;//元素列表后有内容时,要加;
   private WeekDay()//构造方法要私有
   {
    System.out.println("first");
   }
   private WeekDay(int day)
   {
    System.out.println("second");
   }
  }
 }

 注:运行可看到枚举类分别用到的是哪个构造方法。

16。实现带有抽象方法的枚举

 1.知识点:
  1)枚举就相当于一个类,其中也可以定义构造方法,成员变量,普通方法和抽象方法。
  2)枚举元素必须位于枚举体中的最开始部分,枚举元素列表的后要有分号与其他成员分隔。
  把枚举中的成员方法或变量等放在枚举元素的前面,编译器报告错误。
  3)带构造方法的枚举
  构造方法必须定义成私有的
  如果有多个构造方法,该如何选择哪个构造方法?
  枚举元素MON和MON()的效果一样,都是调用默认的构造方法。
  4)带方法的枚举
  定义枚举TrafficLamp
  实现普通的next方法
  实现抽象的next方法:每个元素分别是由枚举类的子类来生成的实例对象,这些子类采用
  类似内部类的方式进行定义。
  增加上表示时间的构造方法
  5)枚举只有一个成员时,就可以作为一种单例的实现方式。

  6)eclipse中功能之打开工程所在目录:选中工程-->在菜单栏中点open in Explorer
 2.代码演示:
 public enum TrafficLamp
 {
  RED(30)
  {
   public TrafficLamp nextLamp()
   {
    return GREEN;
   }
  },
  GREEN(45)
  {
   public TrafficLamp nextLamp()
   {
    return YELLOW;
   }
  },
  YELLOW(5)
  {
   public TrafficLamp nextLamp()
   {
    return RED;
   }
  };
  public abstract TrafficLamp nextLamp();
  private int time;
  private TrafficLamp(int time)
  {
   this.time = time;
  }
 }

 见EnumTest.java

17.透彻分析反射的基础_Class类

 1.反射的基石:Class类
  1)java程序中的各个java类属于同一类事物,描述这类事物的java类名就是Class.
  2)对比提问:众多的人用一个什么类表示?众多的java类用一个什么类表示?
  人-->Person
  Java类-->Class
  3)对比提问:Person类代表人,它的实例对象就是张三,李四这样一个个具体的人,Class
  类代表Java类,它的各个实例对象又分别对应什么呢?
  <1>对应各个类在内存中的字节码,例如:Person类的字节码,ArrayList类的字节码,等等。
  <2>一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,
  <3>不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个空间可分别用一个个
   的对象来表示,这些对象显然具有相同的类型,这个类型是什么呢?
  4)如何得到各个字节码对应的实例对象(Class类型)
  <1>类名.class,例如:System.class
  <2>对象.getClass(),例如:new Date().getClass()
  <3>Class.forName("类名"),例如:Class.forName("java.util.Date")//查询或加载
  5)九个预定义Class实例对象:
  <1>参看Class.isPrimitive方法的帮助
  <2>Int.class == Integer.TYPE
  6)数组类型的Class实例对象
  <1>Class.isArray()
  <2>总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如:int[],void...
 2.class与Class的区别:
  class是指java类,java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,
  则由这个类的实例对象来确定,不同的实例对象有不同的属性值。java程序中的各个类,也属于同一类事物,
  Class类是用来描述java程序中的各个java类这一事物的,Class类描述了类的名字,类的访问属性,类所属于
  的包名,字段名称的列表,方法名称的列表等等。
 3.Class.forName("java.lang.String");中forName()的作用:
   返回字节码。有两种方式:第一,字节码已加载过。第二,字节码未被加载过,在java虚拟机中还不存在,
   则用类加载器去加载,然后缓存到虚拟机中,以后就不用再加载了。
 4.代码演示:
  Person p1 = new Person();
  Person p2 = new Person();
  Date
  Math

  Class cls1 = Date.class//字节码1;
  Class cls2 = Person.class//字节码2;

  p1.getClass();//用对象的方法可得到类名

  Class cls1 = void.class;

  另见RefectTest.java

18.理解反射的概念

 1.反射就是把Java类中的各种成分映射成相应的java类。例如,一个java类可用一个Class类的对象来
   表示,一个类中的组成部分有:成员变量,方法,构造方法,包等等信息也可用一个个的java类来
   表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个类。表示java类的Class类显然
   要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用
   相应类的实例对象来表示,它们是Field,Method,Contructor,Package等等。
  2.一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法
  可以得到这些实例对象。然后再使用这些对象。

19.构造方法的反射应用

 1.Constructor类
  1)Constructor类代表某个类中的一个构造方法。
  2)得到某个类所有的构造方法:
    例子:Constructor[] contructors = Class.forName("java.lang.String").getConstructors();
  3)得到某一个构造方法:
  例子:Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
  //获取方法时要用到类型
  4)创建实例对象:
  <1>通常方式:String str = new String(new StringBuffer("abc"));
  <2>反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));
  //调用获得的方法时要用到上面相同类型的实例对象
  5)Class.newInstance()方法:
  <1>例子:String obj = (String)Class.forName("java.lang.String").newInstance();
  <2>该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
  <3>该方法内部的具体代码是怎样写的呢?用到了缓存机制来保存默认构造方法的实例对象。
 2.一个类有多个构造方法,用什么方式可以区分清楚想得到其中的哪个方法呢?根据参数的个数
  和类型,例如:Class.getMethod(name,Class...args)中的args参数就代表所要获取的那个方法的
  各个参数的类型的列表。重点:参数类型用什么方式表示?用Class实例对象。
  例如:int.class,(int[]).class
     int[] ints = new int[0];
     ints.getClass();

  Constructor对象代表一个构造方法,Constructor对象上会有什么方法呢?得到名字,得到所属于的类,
  产生实例对象。
 3.查看源程序
  传统方式创建实例对象是怎样做的?String str = new String(new StringBuffer("abc"));

 4.代码演示见RefectTest.java
  
  //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));

20.成员变量的反射
 1.Field类
  1)Field类代表某个类中的一个成员变量。
  2)注意:得到的Field对象是对应到类上面的成员变量,不是对应到对象上的成员变量,
     字段fieldX代表的是x的定义,而不是具体的x变量。
 2.exlipse使用技巧:
  1)自动生成java类的构造方法
  右键-->source-->General Constructor using Fields(生成构造方法的源代码)

  注:也可用快捷键:Alt+Shift+S
  2)导包
    例:选中Constructor-->选择import"java.lang.reflect.Constructor"
 3.代码演示:

  package cn.itcast.day1;

public class ReflectPoint
{
 private int x;
 public int y;
 public ReflectPoint(int x, int y) {
  super();
  this.x = x;
  this.y = y;
 }

}

package cn.itcast.day1;

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

public class ReflectTest
{
 public static void main(String[] args)throws Exception
 {
 
  
  ReflectPoint pt1 = new ReflectPoint(3,5);
  Field fieldY = pt1.getClass().getField("y");
  //fieldY的值是多少?不是5,fieldY不是对象身上的变量,而是类上,要用它去取某个对象上对应的值。
  System.out.println(fieldY.get(pt1));
  Field fieldX = pt1.getClass().getDeclaredField("x");//x 是私有变量,是看不见的,此方法则可看见,但不能用
  fieldX.setAccessible(true);//暴力反射:可强制使用已看到但不能用的私有变量。
  System.out.println(fieldX.get(pt1));
 }

}

 

 

以下是我的程序代码:

 

 


//Sting 是一个类不是一个基本数据类型。
//总之只要是在源程序中出现的类型都有各自的Class实例对象,例:int[] ,void。
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.ArrayList;
import java.util.HashSet;
import java.io.InputStream;
import java.io.FileInputStream;
import java.util.Properties;
import java.beans.PropertyDescriptor;
import java.beans.BeanInfo;
import java.beans.Introspector;

class Demo1{
 public static void main(String args[]){
  //创建一个字符串对象。
  String str1 = "abc";
  //通过字符串对象来得到它的字节码文件对象。
  Class cls1 = str1.getClass();
  //通过String类来得到String类的字节码,  只要在程序中用到了某类名,JVM就把它加载到内存了来。
  Class cls2 = String.class;
  //当JVM内存中没有该字节码时通过让类加载器把该字节码
  //加载到内存中。
  Class cls3 = null;
  try{
    cls3 = Class.forName("java.lang.String");
  }catch (ClassNotFoundException e){
   e.printStackTrace();
  }
  //证明三份字节码是否是同一个字节码文件。因为一分字节码可搞出多个实例对象来。
  System.out.println((cls1 == cls2)+"...."+(cls2 == cls3));
  //打印字符串的字节码是不是原始类型。
  System.out.println("字符串的字节码是原始类型"+cls1.isPrimitive());
  //打印void的字节码是不是原始类型。
  System.out.println("void 的字节码是原始类型"+void.class.isPrimitive());
  //打印int的字节码是不是原始类型。
  System.out.println("int 的字节码是原始类型"+int.class.isPrimitive());
  //判断int型和Integer型的字节码是否相同。 
  System.out.println(int.class == Integer.class);
  //Integer(包装类)里面专门定义了一个常量TYPE,该常量表,包装类
  //里所包装的基本类型的字节码
  System.out.println(int.class == Integer.TYPE);
  //打印的是该包装类里包装的基本类型的字节码。
  System.out.println(Boolean.TYPE);
  //打印的是包装类型的字节码。
  System.out.println(Integer.class);
  System.out.println(Integer.TYPE);
  //打印的是基本数据类型的字节码。
  System.out.println(int.class);
  System.out.println(void.class);
  //看基本数据类型的字节码和包装类里包装的基本数据类型的字节码是否相同。
  System.out.println("基本数据类型和包装类里基本数据类型 相同"+(int.class == Integer.TYPE));
  //看数组的类型是否是原始类型。
  System.out.println("数组的类型是否是原始类型"+(int[].class.isPrimitive()));
  //判断一个字节码文件对象是不是一个数组,用isArray();
  System.out.println("字节码文件对象是不是一个数组"+(int[].class.isArray()));
  System.out.println("----------------------------------");
  
  int i = 5;
  int[] ii = new int[5];
//  Object[] ii = new Object[5];
  int[][] iii = new int[6][];
  int[][][] iiii = new int[6][][];
  //返回表示数组组件类型的 Class。如果此类不表示数组类,则此方法返回 null。
  System.out.println(int.class.getComponentType());
  System.out.println(ii.getClass().getComponentType()+"\t它的类型为:"+ii.getClass().getName());
  System.out.println(iii.getClass().getComponentType());
  System.out.println(iiii.getClass().getComponentType());
  System.out.println(ii.getClass());
 }
}

//如何得到字符串中的这个构造方法:String(StringBuffer buffer) ;

class Demo2{
 public static void main(String args[])throws Exception{
  //用一个StringBuffer对象传给这个对象的构造方法,然后用这个构造方法去new一个字符串。
  //new String(new StringBuffer("abc")); 用反射的方式来完成。
  //通过类的字节码文件对象去调用一个以字节码文件对象为参数的方法,
  //返回的是一个构造方法的对象。
  Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
  //构造方法对象,调用newInstance方法,该方法需要接收一个具体类型的对象为参数,来创建一个新对象。
  //该方法用到了泛型,没指定泛型时返回的对象类型为Object,
  //所以此处需要进行强制类型的转换。
  String str2 = (String)constructor1.newInstance(new StringBuffer("abc"));
  //在编译时无误,运行时报错,类型不匹配,需传一个StringBuffer类型的。
  //因为上句以声明参数类型为StringBuffer。
  //String str2 = (String)constructor1.newInstance("abc");
  System.out.println(str2.charAt(2));
  //根据Class类中的newInstance方法来创建默认构造方法的对象。
  String obj = (String)Class.forName("java.lang.String").newInstance()+"sdfklsdjkfj,,,";
  System.out.println(obj);
 }
}

class ReflectPoint{
 private int x;
 public int y;
 public String str1 = "ball";
 public String str2 = "basketball";
 public String str3 = "itcast";
 public ReflectPoint(int x,int y){
  super();
  this.x = x;
  this.y = y;
 }
 public int getX(){
  return x;
 }
 public void setX(int x){
  this.x = x;
 }
 public int getY(){
  return y;
 }
 public void setY(int y){
  this.y = y;
 }
 public int hashCode(){
  final int prime = 31;//被final修饰的变量称为常量 。
  int result = 1;
  result = prime * result+x;
  result = prime * result+y;
  return result;
 }
 public boolean equals(Object obj){
  if(this == obj)
   return true;
  if(obj == null)
   return false;
  if(getClass() != obj.getClass())
   return false;
  final ReflectPoint other = (ReflectPoint) obj;
  if(x != other.x)
   return false;
  if(y !=other.y)
   return false;
  return true;
 }
 public String toString(){
  return str1+"..."+str2+"..."+str3;
 }
}

class Demo3{
 public static void main(String args[])throws Exception{
  ReflectPoint pt1 = new ReflectPoint(3,5);
  //根据pt1的字节码和类中属性名来获取该类中字段的对象。
  Field fieldy = pt1.getClass().getField("y");
  //返回指定对象上此Field表示的字段值。
  System.out.println(fieldy.get(pt1));
  //当类中属性x被私有后,要取得它的字段将出现:NoSuchFieldException
  //Field fieldx = pt1.getClass().getField("x");
  //访问不可见的属性时用getDeclareDField()方法
  Field fieldx = pt1.getClass().getDeclaredField("x");
  //如果访问私有的属性还会发生不可访问异常。IllegalAccessExcepions
  //可把私有的属性设置成可访问的,通过setAccessible()方法。
  fieldx.setAccessible(true);
  System.out.println(fieldx.get(pt1));
 }
}

//将任意一个对象中的所有String类型的成员变量所对应的字符串
//内容中的“b”改成“a”;


class Demo4{
 public static void main(String args[])throws Exception{
  ReflectPoint pt1 = new ReflectPoint(3,5);

  changeStringValue(pt1);
  System.out.println(pt1);
 }
 //静态方法也能用private修饰。
 private static void changeStringValue(Object obj)throws Exception{
  Field[] fields = obj.getClass().getFields();
  for(Field field : fields){
   //打印不出来私有的属性名。
   System.out.println(field.getName());
   //if(field.getType().equals(String.class))
   //因为字节码有一份,所以用==比较。
   if(field.getType() == String.class){
    String oldValue = (String)field.get(obj);
    String newValue = oldValue.replace('b','a');
    field.set(obj,newValue);
   }
  }
 }
}

 


class Demo5{
 public static void main(String args[])throws Exception{
  String str1 = "abc";
  //根据String类的字节码调用该方法并指定具体方法的名称和参数列表的类型。
  //可理解成该方法对象中封装了某类的字节码,具体方法名和参数类型。
  //在调用时需传指定的对象,参数。
  Method methodCharAt = String.class.getMethod("charAt",int.class);
  //根据指定的对象和参数来调用方法。
  //调用某个方法一定是在某个对象上调用,所以第一个参数
  //是要明确对象。当调用一个方法时需要明确参数,所以传
  //一个具体的参数值。
  System.out.println(methodCharAt.invoke(str1,1));
  //JDK1.4也可用数组来接收。
  System.out.println(methodCharAt.invoke(str1,new Object[]{2}));
 }
}

 


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

 

class Demo7{
 public static void main(String args[])throws Exception{
  //Demo6.main(new String[]{"111","222","333"});//通过一般方法调用
  //定义一个字符串变量接收main方法中的参数。
  String startingClassName = args[0];//通过反射调用。
  //通过传入的参数(类),得到它的字节码,在得到它的main方法对象。
  Method mainMethod = Class.forName(startingClassName).getMethod("main",String[].class);
  //该对象调用并执行它的main方法。
  mainMethod.invoke(null,(Object)new String[]{"111","222","333"});
 }
}

//每一个具有相同数据类型和维数的数组,它们用的是同一个字节码文件。
class Demo8{
 public static void main(String args[])throws Exception{
  int[] a1 = new int[3];
  int[] a2 = new int[4];
  int[][] a3 = new int[2][3];
  String[] a4 = new String[3];//class or interface Lclassname
  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(a3.getClass().getName());
  System.out.println(a4.getClass().getName());//class or interface  Lclassname
  //它们的父类都是Object。
  System.out.println(a1.getClass().getSuperclass().getName());
  System.out.println(a4.getClass().getSuperclass().getName());
  //因为a1和a4都是一维数组类型,它们的父类都是Object所以可用Object接收。
  Object aobj1 = a1;
  Object aobj2 = a4;
  //基本数据类型的数组是不能转换成Object[]数组的。因为基本类型不是类。
  //Object[] aobj3 = a1;
  Object[] aobj4 = a3;
  Object[] aobj5 = a4;
 }
}

class Demo9{
 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(a1.getClass() == a4.getClass());
  //System.out.println(a1.getClass() == a3.getClass());
  System.out.println(a1.getClass().getName());
  System.out.println(a3.getClass().getName());
  System.out.println(a4.getClass().getName());//class or interface  Lclassname
  //它们的父类都是Object。
  System.out.println(a1.getClass().getSuperclass().getName());
  System.out.println(a4.getClass().getSuperclass().getName());
  //因为a1和a4都是一维数组类型,它们的父类都是Object所以可用Object接收。
  Object aobj1 = a1;
  Object aobj2 = a4;
  //基本类型的数组是不能转换成Object[]的。因为基本类型不是类。
  //Object[] aobj3 = a1;
  Object[] aobj4 = a3;
  Object[] aobj5 = a4;
  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 Demo10{
 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");
 }
 public static void printObject(Object obj){
  Class clazz = obj.getClass();
  //判断该字节码文件对象是否是一个数组类。
  if(clazz.isArray()){
   // 以 int 形式返回指定数组对象的长度。
   int len = Array.getLength(obj);
   for(int i=0;i     //返回指定数组对象中索引组件的值,返回的是Object.
    System.out.println(Array.get(obj,i));
   }
  }else{
    System.out.println(obj);
  }
 }
}


//hashCode方法的作用:它的作用是通过HashSet来提现的,只有存储在这种
//集合中它才能发挥作用,它可提高查找的效率,它把数据分为不同的区。
//防内存泄露。
class Demo11{
 public static void main(String args[])throws Exception{
  //用HashSet存储时,总长度为3 ,
  Collection collections = new HashSet();
  //用ArrayList存储时,总长度为4
  //Collection collections = new ArrayList();
  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);//HashSet中它没有存进来。

  //pt1.y = 7;//修改后,因当前哈希值变了,删除不了了,内存泄露了。
  collections.remove(pt1);
  System.out.println(collections.size());
 }
}

 


class Demo12{
 public static void main(String args[])throws Exception{
  //一定要记住用完整的路径,但完整的路径不是硬编码,而是运算出来的。
  InputStream ips = new FileInputStream("config.properties");
  Properties props = new Properties();
  props.load(ips);
  ips.close();//关闭的是流,而非ips。
  String className = props.getProperty("className");
  Collection collections = (Collection)Class.forName(className).newInstance();
  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);//HashSet中它没有存进来。
  //pt1.y = 7;//修改后,因当前哈希值变了,删除不了了,内存泄露了。
  //collections.remove(pt1);
  System.out.println(collections.size());
 }
}

 

class Demo13{
 public static void main(String args[])throws Exception{
  //InputStream ips = Demo13.class.getClassLoader().getResourceAsStream("config.properties"); 
  InputStream ips = Demo13.class.getResourceAsStream("config.properties"); 
  Properties props = new Properties();
  props.load(ips);
  ips.close();
  String className = props.getProperty("className");
  Collection collections = (Collection)Class.forName(className).newInstance();
  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);//HashSet中它没有存进来。
  //pt1.y = 7;//修改后,因当前哈希值变了,删除不了了,内存泄露了。
  //collections.remove(pt1);
  System.out.println(collections.size());
 }
}

 

 

class Demo14{
 public static void main(String args[])throws Exception{
  ReflectPoint pt1 = new ReflectPoint(3,5);
  String propertyName = "x";
  PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());
  Method methodGetX = pd.getReadMethod();
  Object retVal = methodGetX.invoke(pt1);
  System.out.println(retVal);

  Method methodSetX = pd.getWriteMethod();
  methodSetX.invoke(pt1,7);

  System.out.println(pt1.getX());
  
  System.out.println(method1(pt1,propertyName));

  System.out.println("--------------------------------");
  method2(pt1,"x",12);
  System.out.println(method1(pt1,"x"));

 }
 public static Object method1(Object pt1,String propertyName)throws Exception{
  BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());
  PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
  Object retVal = null;
  for (PropertyDescriptor pd : pds){
   if(pd.getName().equals(propertyName)){
    Method methodGetX = pd.getReadMethod();
    retVal = methodGetX.invoke(pt1);
    break;//该句可优化程序性能 。
   }
  }
  return retVal;
 }
 public static void method2(Object pt1,String propertyName,Object value)throws Exception{
  BeanInfo beanInfo = Introspector.getBeanInfo(pt1.getClass());
  PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
  for(PropertyDescriptor pd : pds){
   if(pd.getName().equals(propertyName)){
    Method methodSetX = pd.getWriteMethod();
    methodSetX.invoke(pt1,value);
    break;
   }
  }
 }
}

 

你可能感兴趣的:(黑马程序员-学习日记21(java高新技术 1 ))