黑马程序员-14 Java基础加强1

时间:2021-12-29 00:40:52

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

枚举
有限对象的类

public class EnumTest {  
  
    /** 
     * @param args 
     */  
    public static void main(String[] args) {  
        //普通方法模拟枚举  
        MyWeekDay weekDay=MyWeekDay.SUN;  
        System.out.println(weekDay.nextDay());  
          
        WeekDay weekDay2=WeekDay.FRI;  
        System.out.println(weekDay2);//枚举类提供了toString方法  
        System.out.println(weekDay2.name());//FRI,返回此枚举常量的名称,在其枚举声明中对其进行声明  
        System.out.println(weekDay2.ordinal());//5,返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。  
        System.out.println(weekDay2.getClass());//class cn.itcsat.day1.EnumTest$WeekDay  
          
        //枚举类中的静态方法  
        System.out.println(WeekDay.valueOf("SUN"));//返回带指定名称的指定枚举类型的枚举常量。  
        System.out.println(WeekDay.values().length);//7  
          
    }  
  
    public enum WeekDay{//枚举使用enum关键字  
        SUN(1),MON(2),TUE(3),WED(4),THI(5),FRI(6),SAT(7);  
        private WeekDay(){//枚举构造函数只能使用private  
            System.out.println("first");  
            }  
        private WeekDay(int day){  
            System.out.println("second");  
        }  
    }  
    public enum TrafficLamp{  
        RED(30){  
  
            @Override  
            public TrafficLamp nextLamp() {  
                return GREEN;  
            }  
              
        },  
        GREEN(45){  
  
            @Override  
            public TrafficLamp nextLamp() {  
                return YELLOW;  
            }  
              
        },  
        YELLOW(5){  
  
            @Override  
            public TrafficLamp nextLamp() {  
                return RED;  
            }  
              
        };  
          
        public abstract TrafficLamp nextLamp();  
        private int time;  
        private TrafficLamp(int time){this.time=time;}  
    }  
}  

如果不使用枚举的对照 

public abstract class MyWeekDay {  
      
    private MyWeekDay() {};  
    public abstract MyWeekDay nextDay();//抽象方法  
    /* 
     * public WeekDay nextDay(){ 
     * if(this==SUN){ 
     * return MON; 
     * } 
     * else{ 
     * return SUN; 
     * } 
     * } 
     */  
  
    public final static MyWeekDay SUN = new MyWeekDay() {  
        // 匿名内部类  
        // 定义了一个WeekDay的子类,覆写nextDay方法并实例化对象  
        //这样实现nextDay方法,避免了在同一个nextDay方法中使用大量的if-else语句  
        //采用抽象方法定义nextDay就将大量的if-else语句转移成了一个独立的类※  
        @Override  
        public MyWeekDay nextDay() {  
            return MON;  
        }  
    };  
    public final static MyWeekDay MON = new MyWeekDay() {  
  
        @Override  
        public MyWeekDay nextDay() {  
            return SUN;  
        }  
          
    };  
  
    public String toString() {  
        return this == SUN ? "Sunday" : "Monday";  
    }  
}  

====================================================
反射
  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
  Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

import java.lang.reflect.*;

public class ReflectTest {
    public static void main(String[] args) throws Exception {
        String str1 = "abc";
        
        /*三种获取Class的方式*/
        Class cls1 = str1.getClass();
        Class cls2 = String.class;
        Class cls3 = Class.forName("java.lang.String"); //抛出 ClassNotFoundException
        
        System.out.println(cls1 == cls2);    //true
        System.out.println(cls1 == cls3);    //true
        
        System.out.println(cls1.isPrimitive());                //false
        System.out.println(int.class.isPrimitive());        //ture
        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
        
        //new String(new StringBuffer("abc"));    //通过反射建立这个构造函数
        Constructor constructor1 = String.class.getConstructor(StringBuffer.class);    //获取构造方法    getConstructor(特定类)
        String str2 = (String) constructor1.newInstance(new StringBuffer("abc"));    //newInstance(特定类的对象),返回Object。
    
        //Field    获取类成员变量
        RelectPoint rp1= new RelectPoint(3, 5);
        Field feildY = rp1.getClass().getField("y"); 
        Field feildX = rp1.getClass().getDeclaredField("x"); //获取private成员
        feildX.setAccessible(true);        //设置为可见,强行获取
        System.out.println(feildX.get(rp1) +""+ feildY.get(rp1));
        changeStringValue(rp1);
        System.out.println(rp1.test1 +"  "+ rp1.test2);    //输出aacd  qwaaer
        
        //Method 获取成员函数
        Method methodCharAt = String.class.getMethod("charAt", int.class);    //获取以int作为参数的charAt方法
        System.out.println(methodCharAt.invoke(str1, 1));    //输出b
        
        /*为什么用反射方式调用方法:编译时并不知道要运行方法的类名,作为参数传入*/
        String startingClassName = args[0];    // 主函数传入运行参数 (右键run as -> Run configurations)
        Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);
        mainMethod.invoke(null, (Object)new String[]{"11","22","33"});        //静态方法用null,加(object)防止编译时把String数组拆包
        
        //数组的反射 同维度同类型数组的class字节码相同
        int[] a1 = new int[]{1,2,4};
        int[] a2= new int[4];
        int[][] a3 = new int[2][3];
        String[] a4 = new String[3];        
        System.out.println(a1.getClass() == a2.getClass());
    //    System.out.println(a1.getClass() == a3.getClass()); //编译出错 下同
    //    System.out.println(a1.getClass() == a4.getClass());
        
        printObject(a1);
        printObject("xyz");
    }
    
    private static void changeStringValue(Object obj) //把一个类中所有String成员变量的b换成啊
            throws IllegalArgumentException, IllegalAccessException{
        Field[] fields = obj.getClass().getFields();
        for(Field f:fields)
            if(f.getType() == String.class){
                String oldValue = (String)f.get(obj);
                String newValue = oldValue.replace("b","a");//把b替换成a
                f.set(obj, newValue);
            }
    }
    
    private static void printObject(Object obj){    //打印类。不知道对象是不是·数组,用反射进行判断
        Class clazz = obj.getClass();
        if(clazz.isArray()){
            int len = Array.getLength(obj);
            for(int i = 0;i<len;i++)
                System.out.println(Array.get(obj, i));
        }else
            System.out.println(obj);
    }
}

class RelectPoint{
    private int x;
    public int y;
    public String test1 = "abcd";
    public String test2 = "qwbaer";
    public RelectPoint(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
 
class TestArguments{    //按下F2获取完整类名
    public static void main(String[] args){
        for(String arg:args){
            System.out.println(arg);
        }
    }
}

 

====================================================================

内省>JavaBean(符合某种特定规则的特殊的Java类)
JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性。众所周知,属性名称符合这种模式,其他Java 类可以通过自身机制发现和操作这些JavaBean 属性。

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


public class JavaBeanDemo {

    public static void main(String[] args) 
            throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Point p1 = new Point();
        String propertyName = "x";
        
        /*PropertyDescriptor 描述 Java Bean 通过一对存储器方法导出的一个属性*/
        PropertyDescriptor pd = new PropertyDescriptor(propertyName,p1.getClass());    
        Method methodGetX = pd.getReadMethod();
        Object retVal = methodGetX.invoke(p1);
        System.out.println(retVal);
        
        Method methodSetX = pd.getWriteMethod();
        methodSetX.invoke(p1,1);
        System.out.println( p1.getX() +"");
    }

}

class Point{
    private int x = 3;
    private int y = 4;
    
    //右键-> source -> Generate Getters and Setters 自动生成
    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;
    }
    
}

 

==========================================================
注解(jdk1.5)
注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记。以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。

@SuppressWarnings("deprecation")//压制警告
@Deprecated//标记过时
@Override//提示覆盖

注解类:
@interface A
{
}
应用了“注解类”的类:
@A
Class B
{
}
对“应用了注解类的类"进行反射操作的类:
Class C {
B.class.isAnnotionPresent(A.class);
A a = B.class.getAnnotion(A.class);
}
@Retention(RetentionPolicy.xxx)
元注解,其三种取值:RetetionPolicy.SOURCE、RetetionPolicy.CLASS、RetetionPolicy.RUNTIME;分别对应:java源文件>内存中的字节码。
默认的值在class文件阶段。
@Override source(源文件)阶段
@SuppressWarings Runtime(内存中的字节码)阶段

@Target({ElementType.METHOD,ElementType.TYPE})
Target的默认值为任何元素,设置Target等于ElementType.METHOD,原来加在类上的注解就报错了,改为用数组方式设置{ElementType.METHOD,ElementType.TYPE}就可以了。

注解类:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItcastAnnotation{
    String color() default "blue";
    int[] arrayAttr() default {3,4,5};
}

 

被注解类

@ItcastAnnotation(color = "red")
public class AnnotationsTest {
    public static void main(String[] args) {
        if(AnnotationsTest.class.isAnnotationPresent(ItcastAnnotation.class)){
            ItcastAnnotation annotation = (ItcastAnnotation) AnnotationsTest.class.getAnnotation(ItcastAnnotation.class);
            System.out.println(annotation.color());
            System.out.println(annotation.arrayAttr());
        }
    }
}