Java高级技术

1、 静态导入:

import语句可以导入一个类或某个包中所有类。import static语句导入一个类中的某个静态方法或所有静态方法。例如:

import static java.lang.Math.min;
public class StaticImport {      
       public static void main(String[] args) {             
              System.out.println(min(90, 50));             
              System.out.println(min(35, 39)); 
        }
}

上面的代码是没有出错的,import static 静态导入

2、装箱和拆箱:

自动装箱:指开发人员可以把一个基本数据直接赋给对应的包装类。

Integer i = 2;//装箱Integer i = new Integer(“2”);

自动拆箱:指开发人员可以把一个包装类对象直接赋给对应的基本数据类型。

int j = i;//拆箱

典型应用:

List list = new ArrayList();

list.add(1); list.add(2); list(3);//加入的是对象。

3、增强for循环:只适合取数据,要修改数组或集合中的数据,要用传统方式。

代码1:
	int arr[] = {1, 2, 3};
		for(int num : arr){
			System.out.println(num);
		}
        代码2:
        	List list = new ArrayList();
		list.add(1);
		list.add(2);
		list.add(3);
		for(Object obj : list){
			int i = (Integer)obj;
			System.out.println(i);
		}

看下面如何取出Map中的数据(Map集合是不可以直接迭代的)

1>传统方式1


	Map map = new LinkedHashMap();//LinkedHashMap is a raw type
		map.put("1", "aaa");
		map.put("2", "bbb");
		map.put("3", "ccc");
        
		Set set = map.keySet();// Returns a Set view of the keys contained in this map
		Iterator it = set.iterator();// Returns an iterator over the elements in this set
		while (it.hasNext()) {
			String key = (String) it.next();
			String value = (String) map.get(key);

			System.out.println(key + "=" + value);
		}

2>传统方式2


Set set = map.entrySet();
		Iterator it = set.iterator();
		
		while(it.hasNext()){
			Map.Entry entry = (Entry) it.next();
			String key = (String)entry.getKey();
			String value = (String)entry.getValue();
			System.out.println(key + "=" + value);
		}

3>增强for循环取map的第一种方式

	for(Object obj : map.keySet()){
			String key = (String) obj;
			String value = (String) map.get(key);
			System.out.println(key + "=" + value);
		}

4>增强for循环取map的第二种方式

	for(Object obj : map.entrySet()){
			Map.Entry entry = (Entry) obj;
			String key = (String)entry.getKey();
			String value = (String)entry.getValue();
			
			System.out.println(key + "=" + value);
		}

4、 可变参数:

“…”三个点表示可变参数,可变参数你就把他看成数组 例如:int ...nums

	public void test1() {
		sum(1, 2, 3, 4, 5, 6);
	}
	public void sum(int ...nums){
		//可变参数你就把他看成数组
		int sum = 0;
		for(int i : nums){
			sum += i;
		}
		System.out.println(sum);
	}

注意的问题:

如果是这样的函数public void sum(int ...nums, int x)操作是不对的,因为sum(1, 2, 3, 4, 5, 6);是可变参数,没有对应的int x参数的值。

这样操作是可以的:public void sum(int x, int …nums); sum(1, 2, 3, 4, 5, 6).

如果定义个数组int attr = {1, 2, 3, 4, 5, 6};然后调用sum(attr);

看下面的代码:

	List list = Arrays.asList("1", "2", "3");
		System.out.println(list);
		
		String arr[] = {"1", "2", "3", "4"};
		list = Arrays.asList(arr);
		System.out.println(list);
		
		int nums[] = {1, 2, 3, 5};
		list = Arrays.asList(nums);
		System.out.println(list);

结果:

[1, 2, 3]

[1, 2, 3, 4]

[[I@1bc82e7]

因为Arrays.asList(nums);传入一个基本类型数组(java中就是一个特殊的对象),把数组当成一个对象放里面。

如果把int nums[] = {1, 2, 3, 5};把改成Integer nums[] = {1, 2, 3, 5};把(多个)对象数组传入,这样产生的结果是:[1, 2, 3, 5]

6、 枚举:

一些程序在运行时,它需要的数据不能是任意的,而必须是在一定的范围内的值,jdk5以前采用自定义类来解决,jdk5以后可以直接采用枚举解决。

JDK5新增的enum关键字用于定义一个枚举类:一个枚举也可以由构造函数、字段、方法。

使用枚举需要注意:

1>枚举类也是一种特殊形式的Java类。

2>枚举类中声明的每一个枚举值代表枚举类的一个实例对象。

3>Java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数,但枚举类的构造函数必须为私有的。

4>枚举类也可以实现接口或继承抽象类。

5>JDK5中扩展了swith语句,它除了可以接受int,byte等外,还可以接收一个枚举类型。

6>若枚举类只有一个枚举值,则可以当作单态设计模式使用。

例如:

//用单态设计模式定义出一个类。

enum A{//class

A;//Object

}

介绍枚举具体用法:

public class Demo4 {
	//枚举
	@Test
	public void test(){
		print(Grade.B);
	}
	public void print(Grade g) { //A B C D E
	}

}
//JDK5以前的解决方案。
/*
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();
	public static final Grade E = new Grade();
}
*/
//JDK5之后的解决方案。
enum Grade{
	A, B, C, D, E;
}

在枚举中添加构造方法:

public class Demo4 {
	//枚举
	@Test
	public void test(){
		print(Grade.B);
	}
	public void print(Grade g) { //A B C D E
		System.out.println(g.getValue());
	}

}
enum Grade{
	A("100-90"), B("89-80"), C("79-70"), D("69-60"), E("59-50"); 
	
	private String value;
	private Grade(String value){//构造函数
		this.value = value;
	}
	public String getValue(){//对外共享数据
		return value;
	}
}

带抽象方法的枚举:

enum Grade{
	A("100-90"){
		public String localValue(){
			return "优";
		}
	}
	,
	B("89-80"){
		public String localValue(){
			return "良";
		}
	}
	,
	C("79-70"){
		public String localValue(){
			return "一般";
		}
	}
	,
	D("69-60"){
		public String localValue(){
			return "差";
		}
	}
	, 
	E("59-50"){
		public String localValue(){
			return "不及格";
		}
	}; 
	
	private String value;
	private Grade(String value){
		this.value = value;
	}
	public String getValue(){
		return value;
	}
	public abstract String localValue();//  抽象方法
}

Java中声明的枚举类,均是java.lang.Enum类的孩子,它继承了Enum类的所有方法。

常用的方法:

name(); ordinal(); valueOf(Class enumClass, String name) ; 

value():此方法虽然在JDK文档中查不到,但每个枚举类都具有该方法,它用于遍历枚举的所有枚举值。

7、 反射(用来做框架的)

反射就是加载类,并解剖出类的各个组成部分。

加载类:Java中有一个Class类,用于代表某个类的字节码。

Class类既然代表某个类的字节码,它当然就要提供加载某个类字节码的方法:forName().

forName()方法用于加载某个类的字节码到内存中,并使用class对象进行封装。

其它两种得到class对象的方式:

1>类名.class

2>对象.getClass()

Forexample:

Class clazz1 = Class.forName("/day01/src/com/company/demo1/People");

Class clazz2 = People.class;

Class clazz3 = new People().getClass();

解剖类:

Class类方法:

public Constructor<T> getConstructor(Class<?>... parameterTypes)

public Method[] getMethods()

public Field[] getFields()

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

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

public Field getDeclaredField(String name)

具体用法查询API.

小技巧:取得类的全称:在类上右击 -> Copy Qulified Name

实例:

私有的方法和属性能不能被外部访问?

私有的数据不能被外界访问,但是反射可以做到这一点。

Person.java

package com.company.demo1;

public class Person {

public String name = "测试";

public Person() {

System.out.println("person");

}

public Person(String name) {

System.out.println("person:" + name);

}

public Person(String name, int password) {

System.out.println("person" + name + ":" + password);

}

private Person(List list) {

System.out.println("list");

}

}

测试类:

public class Demo3 {

	// 反射类的方法:public void aa1()
	@Test
	public void test1() throws Exception {

		Person p = new Person();
		Class clazz = Class.forName("com.company.demo1.Person");
		Method method = clazz.getMethod("aa1", null);
		method.invoke(p, null);
	}

	// 反射类的方法:public void aa1(String name, int password)
	@Test
	public void test2() throws Exception {

		Person p = new Person();
		Class clazz = Class.forName("com.company.demo1.Person");
		Method method = clazz.getMethod("aa1", String.class, int.class);
		method.invoke(p, "张飞", 26);
	}

	// 反射类的方法:public Class[] aa1(String name, int[] password)
	@Test
	public void test3() throws Exception {

		Person p = new Person();
		Class clazz = Class.forName("com.company.demo1.Person");
		Method method = clazz.getMethod("aa1", String.class, int[].class);
		Class[] cla = (Class[]) method.invoke(p, "小飞", new int[] { 1, 2, 3 });

		System.out.println(cla[0]);
	}

	// 反射类的方法:private void aa1(InputStream in)
	@Test
	public void test4() throws Exception {

		Person p = new Person();
		Class clazz = Class.forName("com.company.demo1.Person");
		Method method = clazz.getMethod("aa1", InputStream.class);//相同的错误
		method.invoke(p, new FileInputStream("d:\\a.txt"));

	}
	// 反射类的方法:public static void aa1(int num)
	@Test
	public void test5() throws Exception {
		
		Class clazz = Class.forName("com.company.demo1.Person");
		Method method = clazz.getMethod("aa1", int.class);
		method.invoke(null, 23);
	}

利用Method执行方法:

Method对象提供了如下方法,用于执行它所代表的方法:

public Object invoke(Object obj, Object… args) 

练习:使用Method分别执行无参、有参、多个参(带数字和基本数据类型)、静态、私有方法。

研究下面的代码;

Person

public class Person {

public Person() {

System.out.println("person");

}

public void aa1(){

System.out.println("aa1");

}

public void aa1(String name, int password){

System.out.println(name + ":" + 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);

}

}

对应的解析类Demo3

public class Demo3 {

	// 反射类的方法:public void aa1()
	@Test
	public void test1() throws Exception {

		Person p = new Person();
		Class clazz = Class.forName("com.company.demo1.Person");
		Method method = clazz.getMethod("aa1", null);
		method.invoke(p, null);
	}

	// 反射类的方法:public void aa1(String name, int password)
	@Test
	public void test2() throws Exception {

		Person p = new Person();
		Class clazz = Class.forName("com.company.demo1.Person");
		Method method = clazz.getMethod("aa1", String.class, int.class);
		method.invoke(p, "张飞", 26);
	}

	// 反射类的方法:public Class[] aa1(String name, int[] password)
	@Test
	public void test3() throws Exception {

		Person p = new Person();
		Class clazz = Class.forName("com.company.demo1.Person");
		Method method = clazz.getMethod("aa1", String.class, int[].class);
		Class[] cla = (Class[]) method.invoke(p, "小飞", new int[] { 1, 2, 3 });

		System.out.println(cla[0]);
	}

	// 反射类的方法:private void aa1(InputStream in)
	@Test
	public void test4() throws Exception {

		Person p = new Person();
		Class clazz = Class.forName("com.company.demo1.Person");
		Method method = clazz.getMethod("aa1", InputStream.class);//相同的错误
		method.invoke(p, new FileInputStream("d:\\a.txt"));

	}
	// 反射类的方法:public static void aa1(int num)
	@Test
	public void test5() throws Exception {
		
		Class clazz = Class.forName("com.company.demo1.Person");
		Method method = clazz.getMethod("aa1", int.class);
		method.invoke(null, 23);
	}
}

特殊反射:

反射类的方法:public static void main(String[] args)

如果用下面的方法来

Class clazz = Class.forName("com.company.demo1.Person");

Method method = clazz.getMethod("main", String[].class);

method.invoke(null, new String[]{"aa", "bb"});

用上面的代码来进行反射,会出现下面的错误:wrong number of arguments.

解决方法1

method.invoke(null, new Object[]{new String[]{"aa", "bb"}});

解决方法2

method.invoke(null, (Object)new String[]{"aa", "bb"});

反射类的字段

	@Test
	public void test() throws Exception {
		
		Person p = new Person();
		
		Class clazz = Class.forName("com.company.demo1.Person");
		Field f = clazz.getField("name");
		//获取字段的值
		Object value = f.get(p);
		//获取字段的类型
		Class type = f.getType();
		
		if(type.equals(String.class)){
			String vname = (String)value;
			System.out.println(vname);
		}
		
		//设置name的值
		f.set(p, "值改变了!");
		System.out.println(p.name);
	}

反射私有字段和静态字段方法自己编写代码测试。

8、 内省(Introspector)

为什么要学内省?

开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都使用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作Java对象的属性。

什么是Java对象的属性和对象属性的读写方法?

属性:属性是通过getset方法读写的,有多少个属性,是由setget方法。声明的是字段。

public class Person { //javaBean

	private String name;      //字段
	private String password;  //字段
	private int age;          //字段
	//Ab就是该类的一个属性
	public String getAb(){
		return null;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
}
该类中共有5个属性,其中有getClass(继承Object)中的class属性

使用内省API操作内省属性:

       ---------------------------------------------------------------------------------------------------

   //得到Bean的属性

BeanInfo info = c.getBeanInfo(Person.class);

PropertyDescriptor[] pds = info.getPropertyDescriptors();

for(PropertyDescriptor pd : pds){

System.out.println(pd.getName());

}

---------------------------------------------------------------------------------------------------

上面的代码得到Bean中的所有属性,包括继承Object类的属性。

如果用这段代码代替上面的代码:BeanInfo info = Introspector.getBeanInfo(Person.class, Object.class);这是除去继承Object中的属性。

操作bean指定属性:age

---------------------------------------------------------------------------------------------------

Person p = new Person();

PropertyDescriptor pd = new PropertyDescriptor("age", Person.class);

Method method = pd.getWriteMethod();

method.invoke(p, 45);//设置age属性的值

System.out.println(p.getAge());

---------------------------------------------------------------------------------------------------

获取当前操作的属性的类型:

---------------------------------------------------------------------------------------------------

Person p = new Person();

PropertyDescriptor pd = new PropertyDescriptor("age", Person.class);

System.out.println(pd.getPropertyType());

---------------------------------------------------------------------------------------------------

        课后需要仔细研究的API

        Class Method Field Constructor Instrospector …

9、 泛型:

---------------------------------------------------------------------------------------------------

//自定义泛型的方法

public class Demo1 {

public void testa() {

a("aaa");

}

public <T> T a(T t) {

return t;

}

public <T, E, K> void b(T t, E e, K k){

}

}

---------------------------------------------------------------------------------------------------

<T>声明类型T,使用T t

也可以把泛型声明到类上:public class Demo1 <T, E, K>

静态方法使用泛型用下面的格式:

public static <T> void c(T t){}

面试题:

// 编写一个泛型方法,实现指定位置上的数组元素交换。

public <T> void swap(T arr[], int post1, int post2) {

T temp = arr[post1];

arr[post1] = arr[post2];

arr[post2] = temp;

}

// 编写一个泛型方法,接受一个任意数组,并颠倒数组中的所有元素。

public <T> void reverse(T arr[]) {
		int start = 0;
		int end = arr.length - 1;

		while (true) {
			if (start >= end) {
				break;
			}
			T temp = arr[start];
			arr[start] = arr[end];
			arr[end] = temp;

			start++;
			end--;
		}
	}

版权所有 违法必究 若要转载,请说明出处:http://blog.csdn.net/feilong1105



阅读更多
个人分类: Java教程
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭