当前位置:首页 > 芯闻号 > 充电吧
[导读]一枚举:为什么要有枚举:问题:要定义星期几或性别的变量。该怎么定义?枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中填写的非

一枚举:

为什么要有枚举:

问题:要定义星期几或性别的变量。该怎么定义?

枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量在方式在开发阶段无法实现这一目标。

用普通类如何实现枚举功能,定义一个weekday的类来模拟美剧功能:

私有的构造方法

每一个元素分别用一个共有的静态成员变量表示

可以有若干共有方法或抽象方法,例如:要提供nextDay方法必须是抽象的。

采用抽象方法定义nextDay就将大量的if else语句转移成了一个个独立的类。

如果想在一个类中编写完各个枚举类和测试调用类,那么可以将枚举类定义成调用类的内部类。

枚举的基本应用:

扩展:枚举类的values,valueOf,name,toString,ordinal等方法。

总结:枚举是一种特殊的类,其中的每个元素都是该类的一个实例对象,


public class EnumTest {

 public static void main(String[] args) {

  WeekDay weekDay2 = WeekDay.FRI;

  System.out.println(weekDay2);

  System.out.println(weekDay2.hashCode());

  System.out.println(weekDay2.name());

  System.out.println(weekDay2.ordinal());

  System.out.println(WeekDay.valueOf("SUN").toString());

  System.out.println(WeekDay.values().length);

  //System.out.println(WeekDay.valueOf(, "SUN"));

 }

 

 public enum WeekDay

 {

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

  private WeekDay(){System.out.println("frist");}

  private WeekDay(int i){System.out.println("second");}

 }

}



enum TrafficLamp{
	/**
	 * 匿名对象内部类!
	 * 枚举最简单的创建对象方法:RED,YELLOW,GREEN
	 * 对于普通的类而言,创建对象:Person p = new Person();
	 * 
	 */
	
	RED(30){

		@Override
		public TrafficLamp nextLamp() {
			return YELLOW;
		}
		
	},
	
	YELLOW(40){

		@Override
		public TrafficLamp nextLamp() {
			return GREEN;
		}
		
	},
	
	GREEN(45){

		@Override
		public TrafficLamp nextLamp() {
			return RED;
		}
		
	};
	public abstract TrafficLamp nextLamp();
	private int time;
	private TrafficLamp(int time){
		this.time = time;
	}
	public int getTime() {
		return time;
	}
	public void setTime(int time) {
		this.time = time;
	}
	
}

public class EnumDemo4 {
	public static void main(String[] args) {
		System.out.println(TrafficLamp.RED.nextLamp());
		System.out.println(TrafficLamp.RED.nextLamp().getTime());
		
	}
}

//=================================================

二、内省JavaBean

    JavaBean是一种特殊的Java类,主要用于传输数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。

如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,可以通过setter和getter方法来确定。


    命名规则:setId()的属性名->id

                      isLast()->last

                     setCPU->CPU

                     getUPS->UPS

     总之,一个类被当作JavaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。


2,对JavaBean的简单内省操作

    ReflectPoint pt1 = new ReflectPont(3,5);

    String propertyName  = "x";

    x->X->getX->MethodGetX

    PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());//JavaBean的属性描述类

    Method methodGetX = pd.getReadMethod();

    Objec reVal = methodGetX.invoke(pt1);

    System.out.println(retVal);

    Method methodSetX = pd.getWriteMethod();

     methodSetX.invoke(pt1,7);

    System.out.printn(pt1.getX());//通过普通Java类的方法获得

3,对JavaBean的复杂内省操作

  采用遍历BeanInfo的所有属性方式来查找和设置某个RefectPoint对象的x属性。在程序中把一个类当作JavaBean来看,就是调用IntroSpector.getBeanInfo方法,得到的

   BeanInfo对象封装了把这个类当作JavaBean看的结果信息。

    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;

4,使用BeanUtils工具包操作JavaBean

    先导入beanutils包,在导入logging包,BeanUtils包把上述操作进行封装

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

       BeanUtils.setProperty(pt1,"birthday.time","111");//birthday为Data类型,可以级联操作,操作对象的对象。birthday有setTime方法。

       ProprtyUtils.setProperty(pt1,"x",8);

      注意:BeanUtils类get属性时返回的结果是字符串,set属性时可以接受任意类型的对象,通常使用字符串。

                 用PropertyUtils类get属性时返回的结果为该属性本来的类型,set属性时只接受该属性本来的类型。

//========================================================

三、了解和入门注解的应用

     注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的

     类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。

    看java.lang包,可看到jdk中提供的最基本的annotation.

    @Override重写注解

    @SuppressWarnings  编译器警告注解

    @Deprecated 作废的注解

    注解就相当于一个你的源程序中要调用的一个类,要在源程序中应用某个注解,得先准备好了这个注解类。就像你要调用某个类,得先有开发好这个类。

   

    应用:定义一个最简单的注解:public @interface MyAnnotation{}

                把它加在某个类上:@MyAnnotation public class AnnotationTest{}

                用反射进行测试AnnotationTest的定义上是否有@MyAnnotation

              @MyAnnotation

              public class AnnotationTest{

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

                          if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){

                       MyAnnotation  annotation = (MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class)

                            System.out.println(anntation);

                 }

             }

   }

     @Retention元注解有三种取值:RetetionPolicy.SOURCE、RetetionPolicy.CLASS、RetetionPolicy.RUNTIME;

          分别对应:java源文件,class文件,内存中的字节码

     @Override、@SuppressWarnings是源文件期,@Deprecated是内存中的字节码

    

     @Target元注解

         Target的默认值为任何元素,可以用数组方式设置{ElementType.METHOD,ElementType.TYPE}//ElementType为枚举类,TYPE代表类的类型

      定义基本类型的属性和应用属性:

      在注解类中增加String color();

        @MyAnnotation(color="red")

        用反射方式获得注解对应的实例对象后,再通过该对象调动属性对象的方法。

       为属性指定缺省值:String color() default "yellow";

       value属性:

       String  value() default "xxx";    如果注释中有一个名称为value的属性,且只想设置value属性,那么可以省略value=部分,例:@MyAnnotation("dd").

 //========================================================


四、类加载器

   类加载器:加载类的工具

在java中用到一个类,类加载器把文件字节码问价从硬盘加载到内存

    类加载器也是JAVA类,因为其他java类的类加载器本身也是被类加载器加载,显然必须有第一个类加载器不是java类,这是BootStrap。

     Java虚拟机中的所有类装载器采用具有父子关系的树形结构进行组织,在实例化每个类装载器对象时,需要为其指定一个父级类加载器

对象或者默认采用系统类装载器为其父级类加载。

            

       

类加载器的委托机制:

当java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?

    首先当前线程的类加载器去加载线程中的第一个类。

    如果类A中引用了类B,Java虚拟机将使用加载类A的类装载器来加载类B。

    还可以直接调用ClassLoader.loadClass()方法来指定某个类加载器去加载。

    每个类加载器加载类时,又先委托给其上级类加载器。

     当所有祖宗类加载器没有加载到类,回到发起者类加载器,还加载不了,则抛ClassNotFoundExcepiton,不是再去找发起者类加载器的儿子,因为没有getChild方法,即使有,那么多个儿子,去找哪一个呢?

       每个ClassLoader本身只能分别加载特定位置和目录中的类,但他们可以委托其他的类装载器去加载类,这就是类加载器的委托模式。

        类装载器一级级委托到BootStrap类加载器,当BootStrap无法加载当前所要加载的类时,然后才一级级回退到子孙类装载器去进行真正

        的加载。当回退到最初的类装载器时,如果它自己也不能完成类的装载,那就应报告ClassNotFoundExcepiton异常。

      面试题:能不能自己写个类叫java.lang.System,为了不让我们写System类,类加载采用委托机制,这样可以保证爸爸们优先,也就是

        总是使用爸爸们能找到的类,这样总是使用java系统提供的System.


  //========================================================

五、代理

程序中的代理:要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如:异常处理、日志、计算方法的运行时间、事务管理、等等。

代理类要调用目标类的功能。
目标类  doSomeThing(){
        业务功能代码
            }
代理类  doSomeThing(){
          //前置系统功能代码
           目标对象.doSomeThing()
          //后置系统功能代码

         }   

      

动态代理:

动态代理的工作原理:

1)Client(客户端)调用代理,代理的构造方法接受一个InvocationHandler,client调用代理的各个方法,代理的各个方法请求转发给刚才通过构造方法传入的handler对象,又把各请求分发给目标的相应的方法。就是将handler封装起来,其中this引用了当前的放(发来什么请求就接受哪个方法)。
猜想分析动态生成的类的内部代码:
1、动态生成的类实现了Collection接口(可以实现若干接口),生成的类有Collection接口中的所有方法和一个如下接受InvocationHandler参数的构造方法。
2、构造方法接受一个InvocationHandler对象,接受对象了要干什么用呢?该方法内部的代码会是怎样的呢?
实现Collection接口的动态类中的各个方法的代码又是怎样的呢?InvocationHandler接口中定义的invoke方法接受的三个参数又是什么意思?图解说明如下:

分析为什么动态类的实例对象的getClass()方法返回了正确结果呢?
为何动态类的实例对象的getClass()方法返回了正确结果,而没调用invoke方法:
因为代理类从Object上继承了许多方法,其中只对三个方法(hashCode、equals和toString)进行开发,委托给handler去自行处理,对于它身上其他方法不会交给代理类去实现,所以对于getClass()方法,还是由Object本身实现的。即proxy3.getClass(),该是什么结果还是什么结果,并不会交给invoke方法处理。


自定义代理类的步骤:
方式1:
             获得动态代理类的字节码文件
		Class claz=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
		//通过反射获得该动态代理类的构造方法
		Constructor c=claz.getConstructor(InvocationHandler.class);
	     //编写一个InvocationHandler类
		class myInvocationHandler implements InvocationHandler{

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				// TODO Auto-generated method stub
				return null;
			}
			
		}
		//创建实例,接受一个invocationhandler对象
		c.newInstance(new myInvocationHandler());

方式2,newProxyInstance这个方法需要三个参数,可以直接创建target的代理对象  
        Object proxy3 = Proxy.newProxyInstance(  
                target.getClass().getClassLoader(),  
                /*new Class[]{Collection.class},*/  
                  
                //获取target上的接口  
                target.getClass().getInterfaces(),  
                new InvocationHandler(){  
                  
                    public Object invoke(Object proxy, Method method, Object[] args)  
                            throws Throwable {  
  
                        /*long beginTime = System.currentTimeMillis();  
                        Object retVal = method.invoke(target, args);  
                        long endTime = System.currentTimeMillis();  
                        System.out.println(method.getName() + " running time of " + (endTime - beginTime));  
                        return retVal;*/  
                          
                        //把上边的代码封装到一个类中,让后调用该类的方法,就实现了方法的封装  
                        advice.beforeMethod(method);  
                        Object retVal = method.invoke(target, args);  
                        advice.afterMethod(method);  
                        return retVal;                        
                          
                    }  
                }  
                );  
        return proxy3;  
    }  
  
}
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

Python和Java是两种广泛应用于编程领域的高级编程语言,它们各有优劣。本文从程序设计应用、系统资源占用、高性能处理和语言特点等四方面详细介绍两种编程语言的区别。

关键字: python java 高性能处理

在这篇文章中,小编将为大家带来Java接口的相关报道。如果你对本文即将要讲解的内容存在一定兴趣,不妨继续往下阅读哦。

关键字: java 接口 Interface

应该有不少小伙伴有假期打工的经历,那今天就来给公众号的读者朋友们分享一个二哥编程星球里一个球友在富士康打工 50 天的感受,相信大家看完后会深深触动的。

关键字: 物联网 java 博客

在过去的几年中,Python的普及速度令人惊叹,Java的王者地位也常年不衰。目前两者的竞争愈发激烈,怎么选择成为了许多初学者萦绕心中的问题,网上有很多版本的说法牵引着他们的思维,让本来很简单的问题复杂化。

关键字: python java

我们都知道,浏览一个网页,有两个很主要的“电脑”在共同运行,一台是远程的,为你提供网页数据的“服务器”,一台是你正在使用的客户端电脑。

关键字: javascript java

在各种网页制作技术论坛中,常常有人询问javascript与Java有什么区别,甚至有人误认为javascript就是Java。javascript与Java确实有一定的联系,但它们并不像我们想象的那样联系紧密,甚至可以...

关键字: javascript java

对于很多初学者来讲,不太清楚Java和C语言的区别,为了让那个大家更清晰的了解,近日特意给大家归纳了一些两者的大致区别,希望能够给大家带来一定的帮助作用,也欢迎大家进行详细补充和归纳。

关键字: C语言 java

Java封装案例

关键字: java 实例

今天我们就要来讲讲看似线程安全的双重检查锁单例模式中可能会出现的指令重排问题。

关键字: java 单例模式 双重检查锁

今天我们来放松下心情,不聊分布式,云原生,来聊一聊初学者接触的最多的 java web 基础。

关键字: Spring xml java
关闭
关闭