---------------------- 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");//直接新建对象不放入字符串池
枚举类里面的每一个元素都是一个类的实例对象。
枚举类里面的元素必须位于类的里面的所有成分之前。
枚举类的构造方法必须是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培训、期待与您交流! ----------------------