您的位置:首页 > 职场人生

黑马程序员-java基础加强(一)

2014-05-18 19:26 281 查看
----------------------
ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------

可变参数:

在定义函数的时候,方法接受的参数个数可能是不固定的,这时就要用到java1.5新特性-可变参数

特点:

1.可变参数只能出现在参数列表的最后。

2."..."位于变量类型和变量名之间,前后有无空格都可以。

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

例子:

public class test

{

public static void main(String[] args)

{

System.out.println(add(1,2));

System.out.println(add(1,2,3));

}

public static int add(int x,int ... args)

{

int sum = x;

for(int i=0; i<args.length; i++)

sum += args[i];

return sum;

}

}

枚举:

现实生活中,往往存在这样一些数据集,他们的数据是有限和固定的,例如交通灯的颜色,星期一至星期天,月份等等,此时如果用枚举来描述这种数据集会非常的方便。

枚举类用enum来定义。enum定义的列表成员都是一个对象,并且可以在用枚举中定义的构造函数来构造这些对象。但要注意的是,枚举类中的对象列表必须定义在枚举类

的开头,否则编译器会报错,一次试图往构造函数上传入参数来完成对象的建立是不可能的,编译器会报参数未定义异常。另外可以在枚举中定义抽象函数,在每个枚举对象

中去实现这个函数。

交通等的例子:

public enum Lamp

{

RED

{

public Lamp nextLamp() //覆盖抽象方法

{

return GREEN;

}

},

GREEN

{

public Lamp nextLamp()

{

return YEEELOW;

}

},

YEEELOW

{

public Lamp nextLamp()

{

return RED;

}

};

public abstract Lamp nextLamp();

public String toString()

{

return name();

}

}

public class test

{

public static void main(String[] args)

{

System.out.println(Lamp.RED.next());

}

}

反射:

一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同类的字节码都是不同的,所以它在内存中

的内容也是不同的,将字节码文件中的内容都封装成对象,这样就便于操作这些成员。其实也可以这样考虑,JVM机制要加载各种各样不同的类,

而这些不同的类其实都有一些共性,如有成员变量,成员方法和静态方法等,在加载类时,JVM机制用一些数据结构来存储这些信息,并将这些

信息封装成一个对象,即Class对象,我们便可以从这个对象中获得有关被加载类的一些信息并进行数据的操作。

简单的说:反射就是把java类中的各种成分映射成相应的java类。反射技术可以对一个类进行剖析。反射的好处在于:大大增强了程序的扩展性。

反射的基本步骤:

1.获得相应类的Class对象。

2.实例化对象,获得类的属性,方法或构造函数。

3.访问属性,调用方法,调用构造函数创建对象。

获取Class对象的方法:

1.同过对象调用getClass()方法来获得,这种方式的弊端在于必须要创建对象才能调用getClass()得到Class对象。

2.每一个数据类型都有一个静态的class属性,这种方式的弊端在于必须要明确该类。与前一种方式一样,它们都不利于程序的扩展。

3.使用Class类中的静态方法forName(),根基指定的类名或的该类的Class对象。

Constructor类:一个描述类中构造函数的类,可利用其中的newInstance(Object... initargs)方法来创建一个该类的对象。

例如通过反射来创建一个字符串对象:

Class clazz = Class.forName("String"); //获取String类的Class对象

Constructor constructor = clazz.getConstructor(StringBuffer.class);//获得Constructor对象

String string = (String) constructor.newInstance(new StringBuffer("abc")); //调用newInstance方法来创建一个字符串。

注:在Class类中也有一个newInstance()方法,此方法返回一个通过空参数构造函数创建的对象,实际这个工作完全可以交给Constructor对象来完成。

成员变量的反射(Filed):

Class类中获得Filed对象的方法:

1.Field getField(String name), 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。

2.Field[] getFields() ,返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。

与此对应的方法有:

3.Field getDeclaredField(String name),

4.Field[] getDeclaredFields(String name),

Filed类描述了类中的成员变量。该类中有一些重要的方法:

1.Object get(Object obj), 返回指定对象上此 Field 表示的字段的值。

2.String getName(),返回此 Field 对象表示的字段的名称。

3.Class<?> getType(),返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。

4.void set(Object obj, Object value), 将指定对象变量上此 Field 对象表示的字段设置为指定的新值

例子:

<span style="font-family:KaiTi_GB2312;font-size:18px;">public class test
{
public static void main(String[] args) throws Exception
{
Point p = new Point(3, 5);
java.lang.reflect.Field fieldX = p.getClass().getField("x"); //得到字段名称为"x"的字段的Filed对象
System.out.println(fieldX.get(p)); //输出该字段的值

//y变量是私有的,应获取已声明字段
java.lang.reflect.Field fieldY = p.getClass().getDeclaredField("y");
//设置该字段为可操作的。
fieldY.setAccessible(true);
System.out.println(fieldY.get(p));
}
}

class Point
{
public  int x;
private  int y;
private String str1 = "abcaaaaaabda";
private String str2 = "aaaahghhaaaa";
public Point(int x,int y)
{
this.x = x;
this.y = y;
}
}</span>

在上面的例子中,找出成员属性上所有String类型的变量,并且将字符串中的字符'a'换成字符'b'。

实现这个功能的函数为:

<span style="font-family:KaiTi_GB2312;font-size:18px;">private static void changeString(Object obj) throws Exception
{
Field[] fields = obj.getClass().getDeclaredFields(); //得到关于obj对象上的所有字段的Field对象
for(Field field: fields)
{
if(field.getType() == String.class)  //如果该字段类型是String
{
field.setAccessible(true);   //该字段可能是private,故需要此步骤强制为可操作
String oldString = (String) field.get(obj);   //获得该字段的值
String newString = oldString.replace('a', 'b'); //替换工作
field.set(obj,newString);                  //重新设置该字段的值
System.out.println(field.get(obj));   //输出设置后的值
}
}
}</span>


成员方法的反射(Method)

Class类中获得Filed对象的方法:

1.Method getMethod(String name, Class<?>... parameterTypes),返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。

2.Method[] getMethods(),返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口的公共 member 方法。

与此对应的方法有:

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

4.Method[] getDeclaredMethods()

Method类描述了类中的成员方法。该类中有一些重要的方法:

1.String getName(),返回此 Method 对象表示的方法名称。

2.Class<?>[] getParameterTypes(),按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。

3.Class<?> getReturnType(),返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。

4.Object invoke(Object obj, Object... args),对带有指定参数的指定对象调用由此 Method 对象表示的方法。

例子:

通过反射的方式调用ArrayList中的add方法添加一个元素:

List<String> list = new ArrayList<String>();

Class.forName("java.util.ArrayList").getMethod("add", Object.class).invoke(list, new String("abc"));

System.out.println(list);

用反射的方式调用一个类的main方法:

Class clazz = Class.forName(className).getMethod("main",String[].class);

clazz.invoke(null(Object)new String[]{...args});

数组的反射引用(java.lang.reflect.Array):

Array 类提供了动态创建和访问 Java 数组的方法,其中封装的都是静态方法。

Class类中获得数组信息的方法:

boolean isArray():判定此 Class 对象是否表示一个数组类。

Array中的常见方法:

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

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

3.static Object newInstance(Class<?> componentType, int... dimensions),创建一个具有指定的组件类型和维度的新数组。

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

判断一个对象是否是数组类,是,则打印出每个元素,不是,直接打印。

函数功能实现:

<span style="font-family:KaiTi_GB2312;font-size:18px;">private static void printObj(Object obj)
{
Class clazz = obj.getClass(); //得到对象的Class对象
if(clazz.isArray()) //如果该对象是数组类型的
{
for(int i=0; i<Array.getLength(obj);i++)
System.out.println(Array.get(obj, i));	 //遍历输出该数组中的元素
}
else
{
System.out.println(obj); //否则直接调用该对象的toString方法输出
}
}</span>


----------------------
ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------详细请查看:www.itheima.com


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: