黑马程序员07_基础加强01

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

可变参数、自动装箱拆箱、字符串池、枚举、Class、反射

1、可变参数:适用于参数个数不确定,类型确定的情况。

注意:可变参数出现在参数列表的最后, ...  位于变量类型和变量名之间,前后有无空格都可以。 

可以把可变参数看成是一个数组来使用

package com.itheima.xiaozhi;  
  
public class VariableParameter {  
  
    //可以把可变参数看成是一个数组  
    public static void main(String[] args) {  
        System.out.println(add(1,2,3,4));  
        System.out.println(add(1, new int[] {2,3,4}));  
    }  
      
    public static int add(int a, int...args) {//int[] args  
        for (int i = 0; i < args.length; i++) {  
            a+=args[i];  
        }  
        return a;  
    }  
}  

将一个数组赋给一个可变参数,通常采用的原则是[拆]

比如将new String[ ]{ "1",  "2",  "3"} 赋给String ... strs,是先将String数组拆成三个字符串“1”,“2”,“3”,然后对应赋给可变参数

但是如果将一个int类型的数组赋给可变参数类型Object ... os,采用的原则也是拆吗?

看下面代码

package com.xiaozhi.hellotest;  
  
public class Test {  
  
    public static void main(String[] args) {  
        int[] a=new int[]{1,2,3};  
        System.out.println( a instanceof Object);  
    }  
}  

这两行代码说明int[ ]属于Object的实例,一个简单类型的数组属于一个Object实例,那么将一个简单类型数组赋给Object ... os 可变参数,其实就想当于传了一个Object对象参数而已。所以采用的原则不是拆了。

下面代码页可以证明这一点

package com.itheima.xiaozhi;  
  
import java.util.Arrays;  
import java.util.List;  
  
public class VariableParam {  
  
    public static void main(String[] args) {  
        // public static <T> List<T> asList(T... a)(Object[]os)  
        List list = Arrays.asList("1", "2", "3");  
        System.out.println(list);// [1, 2, 3]  
  
        String arr[] = { "1", "2", "3", "4" };  
        list = Arrays.asList(arr);  
        System.out.println(list);// [1, 2, 3, 4]  
  
        Integer nums2[] = { 1, 2, 3, 4, 5 };  
        list = Arrays.asList(nums2);  
        System.out.println(list);// [1, 2, 3, 4, 5]  
          
        int nums[] = { 1, 2, 3, 4, 5 };  
        list = Arrays.asList(nums);  
        System.out.println(list.size());//1  
        System.out.println(list);// [[I@120d62b]  
  
    }  
}  

2、基本数据类型的自动装箱和拆箱:基本数据类型和它所对应的包装类可以自动转换

比如Integer  i =  1;1自动装箱成为Integer类型

int j = i+1;  i自动拆箱成int类型与1相加

享元设计模式:

integer i1 =3;

integer i2 =3;

i1 == i2  结果是true

integer i3 =137;

integer i4 =137;

i3 == i4 结果是false

对于小的整数(-128 ~ 127),装箱成为的对象都是同一个对象,这就是享元模式的一个小例子

package com.xiaozhi.box;  
  
public class Test {  
  
    public static void main(String[] args) {  
        //自动装箱  
        Integer integer1=13;  
        Integer integer2=13;  
        //自动拆箱  
        System.out.println(integer1+2);  
          
        //享元设计模式:对于小的整数,装箱装成的对象都是同一个  
        System.out.println(integer1==integer2);  
        Integer integer3=137;  
        Integer integer4=137;  
        System.out.println(integer3==integer4);  
    }  
} 

3、字符串池

String s="abc";//放入字符串池,如果池中已经有该字符串,直接使用

String s=new String("abc");//直接新建对象不放入字符串池


4、枚举

枚举类里面的每一个元素都是一个类的实例对象。

枚举类里面的元素必须位于类的里面的所有成分之前。

枚举类的构造方法必须是private私有的。

JDK1.5以后一个枚举类这样写

enum Grade{  
    A,B,C,D;  
}

JDK1.5以前没有枚举类,是这样子做的,构造方法是私有的(只有类内可以创建本类对象)每个对象都是public(公有的,外面可以访问) static (可以通过类名访问)final(不允许改变的)

class Grade{  
  private Grade(){}  
  public static final Grade A=new Grade();  
  public static final Grade B=new Grade();  
  public static final Grade C=new Grade();  
  public static final Grade D=new Grade();  
} 

也就是说当枚举只有一个元素时,可以作为单列的一种实现方式。

enum Grade{
	A
}
带有抽象方法的枚举类,要在创建枚举类的同时实现抽象方法

下面是示例代码,代码中还有values()方法、valueOf(String str)、ordinal()的使用

package com.xiaozhi.enumration;  
  
public class Test {  
  
    public static void main(String[] args) {  
        for(Grade a:Grade.values())  
        System.out.println(a.getScore());  
        		
        System.out.println(Grade.valueOf("A").getScore());//优
        		
        System.out.println(Grade.A.ordinal());//0
    }  
}  
  
enum Grade{  
    A("90-100"){  
        public String getScore(){  
            return "优";  
        }  
    },  
    B("80-90"){  
        public String getScore(){  
            return "良";  
        }  
    },  
    C("70-80"){  
        public String getScore(){  
            return "中";  
        }  
    },  
    D("60-70"){  
        public String getScore(){  
            return "差";  
        }  
    };  
    private String value;  
  
    private Grade(String value) {  
        this.value = value;  
    }  
  
    public String getValue() {  
        return value;  
    }  
  
    public void setValue(String value) {  
        this.value = value;  
    }  
      
    public abstract String getScore();  
} 

5、Class:

内存中的每一份字节码就是一个Class类的实例对象

类是用来描述一类事物的共性,比如人这个类的对象有张三李四王五,而Class的对象有Math.class  Data.class  

如果要加载的类字节码已经被加载过,那么第二次加载就返回已经加载在内存中的字节码。

java中有9个预定义的Class实例对象,基本数据类型boolean byte char short int long float double 和关键字void

isPrimitive()可以判断是否是基本数据类型的字节码

package com.xiaozhi.box;  
  
public class Test {  
  
    public static void main(String[] args) {  
          
          
        System.out.println(int.class == Integer.class);  
        System.out.println(int.class.isPrimitive());//是否是基本数据类型的字节码  
        System.out.println(int.class == Integer.TYPE);//表示基本数据类型int的class实例  
    }  
} 

6、反射:就是把java类中的各个成分映射成相应的java类

例如,一个java类中用一个Class类的对象来表示,一个类的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的java类来表示,就像汽车是一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,他们是Field、Method、Contructor、Package等等。

要反射的类

package com.xiaozhi.reflect;  
  
import java.io.InputStream;  
import java.util.List;  
  
public class Person {  
  
    private String name;  
    private int password;  
      
    public Person() {  
        System.out.println("无参构造函数");  
    }  
  
      
    public Person(String name) {  
        this.name = name;  
        System.out.println("一个参数的构造函数"+name);  
    }  
  
  
    public Person(String name, int password) {  
        this.name = name;  
        this.password = password;  
        System.out.println("两个参数的构造函数"+name+":"+password);  
    }  
      
    private Person(List list){  
        System.out.println("私有构造函数");  
    }  
      
      
    public void aa1(){  
        System.out.println("aa1");  
    }  
    public void aa1(String name,int password){  
        System.out.println("name= "+name+" password="+password);  
    }  
    public Class[] aa1(String name,int[] password){  
        return new Class[]{String.class};  
    }  
    private void aa1(InputStream in){  
        System.out.println(in);  
    }  
    public static void aa1(int num){  
        System.out.println(num);  
    }  
    public static void main(String []args){  
        System.out.println("main");  
    }  
  
}  
加载类的字节码的三种方法

第一种:Class.forName(String str)

第二种:类名.class

第三种:new 类名 .getClass()

反射构造函数调用Class的getConstructor(构造函数的参数的Class对象)

package com.xiaozhi.reflect;  
  
import java.lang.reflect.Constructor;  
import java.util.ArrayList;  
import java.util.List;  
  
  
public class Test {  
  
    public static void main(String[] args) throws Exception {  
        //加载类的字节码的三种方法  
//      Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
//      Class clazz=new Person().getClass();  
//      Class clazz=Person.class;  
          
        //无参的构造函数  
//      Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
//      Constructor constructor=clazz.getConstructor(null);  
//      Person person=(Person) constructor.newInstance(null);  
          
        //一个参数的构造函数  
//      Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
//      Constructor constructor=clazz.getConstructor(String.class);  
//      Person person=(Person) constructor.newInstance("jingtianxiaozhi");  
          
        //两个参数的构造函数  
//      Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
//      Constructor constructor=clazz.getConstructor(String.class,int.class);  
//      Person person=(Person) constructor.newInstance("jingtianxiaozhi",100);  
          
        //私有的构造函数  
//      Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
//      Constructor constructor=clazz.getDeclaredConstructor(List.class);  
//      constructor.setAccessible(true);  
//      Person person=(Person) constructor.newInstance(new ArrayList());  
          
        //默认的  
        Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
        Person p=(Person) clazz.newInstance();  
    }  
      
}
反射方法

getMethod(方法名 ,方法参数)

获取main方法比较特殊,有两种方法:

第一种:把字符串数组包装在一个Object数组中

第二种:把字符串数组强制转换成Object类型,骗过编译器

package com.xiaozhi.reflect;  
  
import java.io.FileInputStream;  
import java.io.InputStream;  
import java.lang.reflect.Method;  
  
public class Test2 {  
  
    public static void main(String[] args) throws Exception {  
        //无参的方法  
        //public void aa1()  
//      Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
//      Method method=clazz.getMethod("aa1",null);  
//      Person person=new Person();  
//      method.invoke(person,null);  
          
        //有参数的方法  
        //public void aa1(String name,int password)  
//      Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
//      Method method=clazz.getMethod("aa1",String.class,int.class);  
//      Person person=new Person();  
//      method.invoke(person,"jingtianxiaozhi",22);  
          
        //有返回值的方法  
        //public Class[] aa1(String name,int[] password)  
//      Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
//      Method method=clazz.getMethod("aa1",String.class,int[].class);  
//      Person person=new Person();  
//      Class cs[]=(Class[]) method.invoke(person,"jingtianxiaozhi",new int[]{1,2,3});  
//      System.out.println(cs[0]);  
          
        //private void aa1(InputStream in){  
//      Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
//      Method method=clazz.getDeclaredMethod("aa1",InputStream.class);  
//      method.setAccessible(true);  
//      Person person=new Person();  
//      method.invoke(person,new FileInputStream("c:\\jingtianxiaozhi.txt"));  
          
        //静态方法  
        //public static void aa1(int num){  
//      Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
//      Method method=clazz.getMethod("aa1",int.class);  
//      method.invoke(null,22);  
          
        //main方法  
        Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
        Method method=clazz.getMethod("main", String[].class);  
        method.invoke(null,new String[]{"13"});//Object...//拆开之后,main方法接受的参数是字符串  
        method.invoke(null,new Object[]{new String[]{"13"}});//Object...//拆开之后,是一个字符串数组  
        method.invoke(null,(Object)new String[]{"13"});  
          
          
    }  
} 
反射字段:

getField(字段名)

package com.xiaozhi.reflect;  
  
import java.lang.reflect.Field;  
  
public class Test {  
  
    public static void main(String[] args) throws Exception {  
        //获取公有字段类型字段值  
//      Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
//      Field field=clazz.getField("name");  
//      Class type=field.getType();  
//      System.out.println(type);  
//      Person person=new Person();  
//      String value=(String)field.get(person);  
//      System.out.println(value);  
          
        //设置公有字段值  
//      field.set(person,"xiaozhi");  
//      System.out.println(field.get(person));  
          
        //获取私有字段类型以及值  
//      Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
//      Field field=clazz.getDeclaredField("password");  
//      field.setAccessible(true);  
//      Class type=field.getType();  
//      System.out.println(type);  
//      Person person=new Person();  
//      Integer value=(Integer)field.get(person);  
//      System.out.println(value);  
          
          
        //获取静态字段类型以及值  
        Class clazz=Class.forName("com.xiaozhi.reflect.Person");  
        Field field=clazz.getField("age");  
        Class type=field.getType();  
        System.out.println(type);  
        Integer value=(Integer)field.get(null);  
        System.out.println(value);  
    }  
}  
  
class Person{  
    public String name="aaa";  
    private int password=123;  
    public static int age=22;  
}

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值