黑马程序员 高新技术上

来源:互联网 发布:c语言write函数 编辑:程序博客网 时间:2024/05/16 12:57

----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------

Java高新技术

Eclipse的操作, 

1.Eclipse  IDE:--->Itegrity Development Environment 

2.更改工程(项目)名:右键—refactorrename

3.注释段落  快捷键:ctrl+shift+/ 效果是:/*  */ 

4.debug界面,Eclipse怎么调试变量:右键—Debug As—选中变量—选watch—在debug透视图里可以看

5.新开的工作间,设置快捷键:WindowpreferenceGeneralKey   如,Alt+/ 是快捷输出Sop

6.模板设置:WindowpreferencejavaeditorTemplates

7.设置JVM内存的大小: JVM默认的内存大小为64M

 设置JVM内存大小的方法是:在所作的项目上面右键>Run Configurations... >VM arguments,在下面输入如下命令:-Xmx1024m,后面的数字可以根据自己的实际情况来设置(这里设置的大小是1024M,即1G),点击 Run,就行了。

修改编码:如果要使新建立工程、java文件直接使UTF-8则需要做以下工作

1windows->Preferences...打开"首选项"对话框,左侧导航树,导航到 general->Workspace,右侧Text  file encoding,选择Other,改变为UTF-8,以后新建立工程其属性对话框中的Text file encoding即为 UTF-8   

2windows->Preferences...打开"首选项"对话框,左侧导航树,导航到 general->Content Types,点开Text,选择Java Source File,在下面的Default encoding输入框中输入UTF-8,点Update,则设置Java文件编码为UTF-8 

 静态导入——>不用在使用其他类的静态成员变量,前缀其类名.这将使代码更简洁, 提高编码效率。

   使用import static 引入静态成员。其中import static java.lang.Math.*;就是静态导入的语法,它的意思是导入Math类中的所有static方法和属性。 这样我们在使用这些方法和属性时就不必写类名。

     需要注意的是默认包无法用静态导入,另外如果导入的类中有重复的方法和属性则需要写出类名,否则编译时无法通过。 

可变参数——>参数个数不确定,类型确定的情况, 减少代码量,方便输入

以往版本的Java中,通常的做法是将多个参数放在一个数组或者对象集合中作为参数来传递,1.5版本开始有可变参数。参数个数不确定,类型确定的情况,java把可变参数当做数组处理。 

可变参数的特点: 减少代码量,方便输入

u 只能出现在参数列表的最后  如:public static int add(int x,int ... args)

l ···位于变量类型和变量名之间,前后有无空格都可以;

l 调用可变参数的方法时,编译器为该变量参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。

 

 

  • 增强for循环——>-减少迭代器(iterator)的潜在错误 

Fortype 变量名 :集合变量名){···}       type是变量类型

如:forint  arg : args ) {···}

 

  • 基本数据类型的自动拆箱和装箱——>无需在基本类型(例如double)和包装类型(例如Double)之间人工地进行转换。 方便了基本类型数据和它们包装类地使用 

Integer  iObj = 3; //将一个基本数据类型自动装箱

System.out.println (iObj + 12); //自动拆箱

Flyweight享元模式: 有很多小的对象,它们有很多相同的属性,把这些相同的属性变为同一个对象,称为内部状态。 把那些不同的属性变为方法的参数,称为外部状态。它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件; 常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。 

 

  • 枚举 (Enum)——> 对值的范围进行限定 ,提高安全性 

枚举类型相当于自己定义一个数据类型,而这个数据类型的名字是自己起的,类型里面的内容也是自己定义的,当用到这个类型的变量时,只能输入已经定义好的内容,这样就可以防止其他程序员输入不符合规定的值. 

为什么要有枚举:

枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。

枚举可以让编译器在编译时就可以控制源程序填写的非法值,普通变量的方式在开发阶段无法实现这一目标。

枚举是一种特殊的类,其中的每个元素都是该类的一个实例对象。枚举元素必须位于枚举体中的最开始部分。

它也可以定义构造方法(必须私有)、成员变量、和抽象方法。

 

枚举总结

  1.构造方法必须定义成私有的 

  2枚举元素必须位于枚举体中的最开始部分。最后一个枚举元素后面加分号

  3.只要用到枚举类,枚举类里的元素都会初始化,调用无参的构造方法

  4.如要调用有参,在元素后面加括号——>里面传入相应的类型参数

  5.枚举里只有一个元素时,就可以作为一种单例的实现方式。

 

          如:public enum Weekday{

                SUN,MON,TUE,WED,THI,FRI,SAT;

               }

 

 

反射

反射:对一个类进行动态的获取并创建对象,并调用该类中的内容。大大的提高了程序的扩展性。

 

反射机制使用特点:

a)      在不明确日后出现什么样的实现类时,可以扩展出去,对外提供配置文件,让后期的实现类都定义在配置文件中。

b)      该程序会读取该配置文件并根据指定的名字找寻具体对应的类。

c)      对找到的类进行对象的建立。

d)      并调用该类对象的成员。

 

反射(Reflection)的功能:

a) 在运行时判断任意一个对象所属的类

b) 在运行时构造一个类的对象

c) 在运行时判断任意一个类所具有的成员变量和方法

d) 在运行时调用任意一个对象的方法

 

在jdk中,主要由以下类来实现java反射机制,这些类位于java.lang.reflect包中

1.       Class类:代表一个类

在java当中,无论生成某个类的多少个对象,这些对象都会对应于同一个Class对象

即一个类对应于一个Class对象。

2.       Field:代表类的成员变量(成员变量也称为类的属性)。

3.       Method类:代表类的方法

4.       Constructor:代表类的构造方法

5.       Array类:提供了动态创建数组,以及访问数组的元素的静态方法

 

Class对象

Class是所有类的对象。它是怎么获取的呢。

获取某个类或某个对象所对应的Class对象常用的有三种方式

a)  使用Class类的静态方法forName,例如Class.forName(“java.lang.String”);

b)  使用类.Class语法.例如:String.class;

c)  使用对象(object)的getClass()的方法。例如String s=aa;Class<?>cla=s.getClass();

这三种所获得的一个类的Class字节码都是一样的

 

九个预定义对象:

基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象,他们都是使用Class类的isPrimitive()方法判断

比如:Integer.Type返回的是int.而Integer.class返回的是Integer所对应的Class对象

 

我们要是判断数组类型的Class实例对象,使用的是isArray()方法。

总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[],void

 

我们看看如下代码演示:

public class ClassDemo {

   public static void main(String[] args)throws Exception{

      //Class对象的字节码判断

      String str="Hello";

      Class c1=str.getClass();

      Class c2=String.class;

      Class c3=Class.forName("java.lang.String");

      System.out.println("c1==c2:"+(c1==c2));//true

      System.out.println("c1==c3:"+(c1==c3));//ture

      //基本类型的判定

      System.out.println(c1.isPrimitive());//true

      System.out.println(int.class.isPrimitive());//true

      System.out.println(int.class==Integer.class);//false

      System.out.println(int.class==Integer.TYPE);//true

      System.out.println(int[].class.isPrimitive());//false

      System.out.println(int[].class.isArray());//true

   }

}

Constructor

Constructor就是构造方法的反射

构造方法

我们通过Class对象的一些方法来获得Constructor的构造方法

获得所有的构造方法:

Constructor<?>[]getDeclaredConstructors()

获得publie所有构造方法

Constructor<?>[]getConstructors() 

获得某一个构造方法

Constructor<T>getConstructor(Class<?>... parameterTypes)

创建实例对象两种方式

a)      先获得Class对象,然后通过该Class对象的newInstance()直接生成即可,例如:

Class<?> classType=String.class;

Object obj=classType.newInctance();

b)      先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过该Constructor对象的newInctance()方法生成,例如:

Class<?> classType()=Cunstomer.class;

Constructor cons=classtype.getConstructor(new Class[]{});

Object obj=cons.newInstance(new Object[]{});

 

若想通过类的的带参数的构造方法生成对象,只能使用下面这一种方式:

Class<?> classType()=Cunstomer.class;

Constructor cons=classtype.getConstructor(newClass[]{String.class,int.class});

Object obj=cons.newInstance(new Object[]{“hello”,3});

比如:

普通方式:

StringBuffer sb=new StringBuffer(newStringBuffer(“abc”));

反射方式:

String str=(String)Constructor.newInstance(new StringBuffer(“abc”));

 

Field

Field类都是成员变量的反射

构造方法都是通过Class对象获取的

构造方法:

获得指定的无需访问权限的Field:

Field getDeclaredField(String name)

获得所有的Field

Field[] getFields() 

获得publie 的某个Field

Field getField(String name)

 

Field类的常用方法

a)      Object get(Object obj): 返回指定对象上此 Field 表示的字段的值

b)      void setAccessible(boolean flag):将此对象的 accessible 标志设置为指示的布尔值。

 

比如如下代码所示:

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

 

public class FieldClass {

   public static void main(String[] args)throws Exception {

      FieldDemo fd=new FieldDemo(3,5);

      //取出FieldDemox

      Field fieldx=FieldDemo.class.getField("x");

      Object objx=fieldx.get(fd);

      //取出FieldDemoy

      Field fieldy=FieldDemo.class.getDeclaredField("y");

      //由于yprivate修饰的,所以暴力反射成可取的值

      fieldy.setAccessible(true);

      Object objy=fieldy.get(fd);

     

      System.out.println("x=="+objx+",y=="+objy);

   }

}

class FieldDemo{

   public int x;

   private int y;//private修饰的field

   FieldDemo(int x,int y){

      this.x=x;

      this.y=y;

   }

}

Method

Method是成员方法的反射

构造方法都是通过Class对象获取的

构造方法:

获得所有的方法:

Method[] getDeclaredMethods() 

获得无限制的指定方法

Method getDeclaredMethod(String name,Class<?>... parameterTypes)

获得所有public方法

Method[] getMethods()

获得指定public方法

Method getMethod(String name,Class<?>... parameterTypes)

 

Method的常用方法

调用一个类的指定的方法

Object invoke(Object obj, Object... args)

如果是调用时指定类的静态方法,那么Objectinvoke (null,Object….args)

我们代码演示下:

import java.lang.reflect.Method;

 

public class MethodTest {

   public static void main(String[] args)throws Exception {

      String str="Hello";

      //指定String类的charAt方法

      Method charAtMethod=String.class.getMethod("charAt",int.class);

      System.out.println(charAtMethod.invoke(str, 4)); 

      //指定String类的subString方法

      Method subMethod=String.class.getMethod("substring",int.class,int.class);

      System.out.println(subMethod.invoke(str, 1,3));

  

      //获得此类的所有方法

      Method[] allMethod=String.class.getDeclaredMethods();

      for (Method me:allMethod){

        System.out.println(me);

      }

   }

}

Array

Array类就是数组的反射

Array的常用方法是:

a)  static Object get(Object array, int index) :返回指定数组对象中索引组件的值。

b)  static int getLength(Object array):以 int 形式返回指定数组对象的长度。

c)  static Object newInstance(Class<?> componentType, int length):创建一个具有指定的组件类型和长度的新数组。

d)  static void set(Object array, int index, Object value):将指定数组对象中索引组件的值设置为指定的新值。

 

如下面代码演示

import java.lang.reflect.Array;

 

public class ArrayDemo {

   public static void main(String[] args) {

     

      int[] a ={1,2,3,4,5};

      Class clazz=a.getClass();

      if (clazz.isArray()){

        int len=Array.getLength(a);//获得数组的长度

        for(int i=0;i<len;i++){

           System.out.println(Array.get(a, i));

        }

      }

   }

}

 

反射的框架应用

反射是经常用在框架上的,当我们需要某个类时,可在配置文件里使用键值对来指定我们需要的引用的类。比如我们新建一个文件名称是config.properties,里面写上classname=java.util.ArrayList.注意这里值不要用双引号。那么我们使用反射来实现一个小小的框架。代码演示如下:

import java.io.FileInputStream;

import java.io.InputStream;

import java.util.*;

 

public class FrameDemo {

   public static void main(String[] args)throws Exception {

      //关联系统中次配置文件

      InputStreamin=new FileInputStream("config.properties");

      Properties pro=new Properties();

      pro.load(in);//加载此配置文件

      //获得此配置文件中key对应的我们要取的对象

      String className=pro.getProperty("classname");

      //将此对象使用反射来获得实例

      Collection coll=(Collection) Class.forName(className).newInstance();

     

      coll.add(new Point(3, 3));

      coll.add(new Point(5, 5));

      coll.add(new Point(3, 3));

     

      System.out.println(coll);

   }

}

class Point{

   int x;

   int y;

   public Point(int x,int y) {

      this.x=x;

      this.y=y;

   }

   @Override

   public String toString() {

      return "x=="+x+",y=="+y;

   }

}

我们在加载配置文件的时候(上面红色部分替换掉)建议使用这行代码,以后在开发时有用

InputStream in=

FieldDemo.class.getResourceAsStream("config.properties");

 

JavaBean

想要对JavaBean操作就是内省IntroSpector,javaBean是特殊的Java类。

Javabean属性是根据方法名来的,主要是用于传递数据信息

 

第一种抽取Javabean方法:

Javabean包下有个类是PropertyDescriptor它描述 Java Bean 通过一对存储器方法导出的一个属性

常用的方法:

a)  构造方法:PropertyDescriptor(String propertyName, Class<?> beanClass):传入一个成员值,并传入类是javaBean的对象

b)  Method getReadMethod() :获得JavaBean的get方法

c)  Method getWriteMethod()  :获得javabean的set方法

 

代码演示如下:

import java.beans.PropertyDescriptor;

import java.lang.reflect.Method;

 

public class JavaBeanDemo {

   public static void main(String[] args)throws Exception {

      Point p=new Point(3, 5);

     

      String propertyName="x";

      PropertyDescriptor pd=new PropertyDescriptor(propertyName,Point.class);

      //获得get方法

      Method meGetX= pd.getReadMethod();

      //调用get方法

      Object retVal=meGetX.invoke(p);

      System.out.println(retVal);

     

      Object value=7;

      //获得set方法

      Method meSetY=pd.getWriteMethod();

      //调用set方法并传值

      meSetY.invoke(p, value);

      System.out.println(meGetX.invoke(p));

   }

}

//javabean

class Point{

   private int x;

   private int y;

   public Point(int x,int y) {

      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;

   }

}

 

第二种抽取JavaBean的方法:

第二种我们使用内省器Introspector来抽取出BeanInfo的方法

Instrospector有个静态的方法是getBeanInfo(Class beanClass),向这个方法传递一个javaBeanClass对象,获得一个BeanInfo对象,可以通过这个对象的方法获得PropertyDescriptor,然后通过它来操作Bean的方法。BeanInfo可以操作属性,方法,和事件

 

比如我们对上面进行第二种写法的过程,类Point我们借用上面的。

public class JavaBeanDemo {

         publicstatic void main(String[] args) throws Exception {

                   Pointp = new Point(3, 5);

                  

                  

                   StringpropertyName = "x";

                   //第一步:通过内省器来获得BeanInfo

                   BeanInfobean = Introspector.getBeanInfo(Point.class);

                   //第二步:BeanInfo对象获得后可以对方法,属性,事件操作。

                   //这里我们通过它的方法getPropertyDescriptors()来获得PropertyDescriptor数组

                   PropertyDescriptor[]pd = bean.getPropertyDescriptors();

                   //遍历PropertyDescrptor数组,并通过它的方法来对bean进行操作

                   for(PropertyDescriptor pds : pd) {

                            Class<?>clazz = pds.getPropertyType();

                            if(clazz == null)

                                     continue;

                            System.out.println("Propertytype:" + clazz.getName());

                            System.out.println("Propertyname:" + pds.getName());

                            //判断所获得的变量名是否是x

                            if(pds.getName().equals(propertyName)) {

                                     MethodgetXMethod = pds.getReadMethod();

                                     Objectretval = getXMethod.invoke(p);

                                     System.out.println(retval);

                                     break;

                            }

                   }

         }

}

 

第三种抽取JavaBean方法:

使用的Apache的开源BeanUtils工具包 的jar包,来操作Bean。而且我们还要下载一个logging包,否则会报错,在BeanUtils中,JavaBeam类必须是public。否则会抛出NoSuchMethodException

在Beanutils包有两种抽取Javabean的方法:

a)      第一种:BeanUtils类

b)      第二种:ProperUtils类

它们都有两个方法:分别是

a)  获得set方法,setProperty(bean,name,value);

b)  获得get方法:getProperty(bean,name);

 

代码演示如下:

注:依然引用上面的Point类

import org.apache.commons.beanutils.BeanUtils;

import org.apache.commons.beanutils.PropertyUtils;

 

public class JavaBeanDemo {

   public static void main(String[] args)throws Exception {

      Point p = new Point(3, 5);

      String propertyName = "y";

     

      System.out.println("----------BeanUtils----------");

      System.out.println("x=="+BeanUtils.getProperty(p,"x"));

      BeanUtils.setProperty(p, "x",9);

      System.out.println("x=="+p.getX());

      System.out.println("----------Properutils-----------");

      System.out.println("y=="+PropertyUtils.getProperty(p,"y"));

      PropertyUtils.setProperty(p, "y", 3);

      System.out.println("y=="+p.getY());

   }

}

 

类加载机制剖析

系统加载器

系统默认三种类加载器:

a) BootStrapclassLoader:JRE/lib/rt.jar,根类加载器

它被称为引导类加载器,它负责加载java的核心类,它不是ClassLoader的子类,是jvm自身实现的,即不是java实现的。

b) ExitClassLoader(ExtensionClassLoader):,扩展类加载器

它负责加载JRE/lib/exit/下面的jar包的类,这样可以为java扩展核心类以外的类。

c) AppClassLoader(System classLoader):classpath指定的所有jar包或目录。系统类加载器

它负责JVM启动时加载来自java命令的的classPath环境变量所指定的jar包和类

d) 指定特殊的目录:这里放置的是我们自定义加载器,用户类加载器

这上面三个类是继承关系的,Bootstrap是顶类,AppClassLoader继承ExitClassLoader

这里的继承关系是类加载器实例之间的关系,不是传统的意义。

 

这里涉及到一个委托机制:

类加载器从AppClassLoader开始即发起者,如果找不到指定的类,就交给父类ExitClassLoader,如果父类没找到就交给顶类Bootstrap,如果找到就可以进行加载,如果还是找不到,就往回返,返回到发起者就会停止报错。所以通常情况下AppClassLoader下的子类是不会被加载到的,除非我们可以自定义加载器

 

我们代码演示下JVM类的类加载器

import java.io.*;

import java.net.*;

import java.util.*;

class ClassLoaderProTest

{

         publicstatic void main(String[] args) throws Exception

         {

                   ClassLoadersystemLoader=ClassLoader.getSystemClassLoader();

                   System.out.println("获取系统加载器:"+systemLoader);

                   //获取系统类加载器的加载路径

                   Enumeration<URL>emu=systemLoader.getResources("");

                   while(emu.hasMoreElements())

                   {

                            System.out.println(emu.nextElement());

                   }

 

                   ClassLoaderparentLoader=systemLoader.getParent();

                   System.out.println("获得此加载器的父类扩展类:"+parentLoader);

                   System.out.println("扩展类加载器的加载路径:"+System.getProperty("java.ext.dirs"));

                   System.out.println("扩展类");

         }

}

从以上代码可以看出它们分别加载的路径是什么?扩展类的加载路径是JRE/lib/exit/

系统加载器加载的路径是程序运行的当前路径。

类加载机制

1)   全盘负责:当一个加载器加载某个类的时候,这个类所引用的或依赖其他的class也将由此加载器加载,除非特别显式其他加载器来加载

2)   父类委托:加载一个类时,试图让父类(parent)先加载该class,只有在父类无法加载该类时,才尝试从自己的加载路径来加载。

3)   缓存机制:它将会保证所有被加载的Class都被缓存,当程序需要使用某个类时,先在缓存中查找该类,如果该类不存在该Class对象,系统才会读取二进制数据,将其转换成Class对象,存入缓存中。这也就是为什么修改了程序还要执行编译命令的原因。

 

自定义加载器

自定义加载器必须继承ClassLoader,是为了覆盖findclass,得到class文件来转换成字节码,

这种转换的方法是defineClass()。

 


原创粉丝点击