加强eclipse的使用技巧。可变参数。基本数据类型自动装箱和拆箱。枚举。反射。数组反射的应用。ArrayList和HashSet。JavaBean

 /*

eclipse的使用技巧。可变参数。基本数据类型自动装箱和拆箱。枚举。反射。数组反射的应用。ArrayList集合和HashSet集合。
JavaBean。
*/


/*基础加强和JDK1.5新特性.

	基础很重要,就业就看基础掌握的好不好.
	但不能天天学基础,只有通过高级的应用,才能知道基础怎么用.
	就像一年纪的题目,五年纪的人来做能拿满分.

eclipse的使用技巧。
	MyEclipse是eclipse的插件。可以处理j2ee.
	eclipse用javaw.exe运行,不再是java.exe.

	ide-->itegrity development environment (集成开发环境)

	1)Workspace与project
		必须要求:会切换工作间与导入项目。

	IDE开发工具都支持使用工程化方式管理一个项目的程序开发过程。一般
	来说一个相对独立的项目就是一个工程,一个项目中涉及的多个java文件,资源
	文件等用一个工程进行管理。

	点window-->点击Preferences-->Java-->Compiler(编译器)。有java版本。编译时版本。
	Java->Installed JREs(java运行版本) 。运行时版本。

	切换工作间:File->Switch Workspace.选择Others,OK后就新建。

	新建一个工程,普通的java工程,New->Project->java Project->输入工程名字。这时可以选用jre版本。
	在src上,可以选择新建class.会选择新建包名。良好的习惯应该有包名。

	修改工程名字,-->Refactor(重构),新建立的工程配置环境可能改变,如快捷键。

	配置快捷键。window-->Preferences->General-->Keys.输入content.
	选择content Assist-->按下UnbindCommand(解除绑定)。在下面可以Binding,按下Alt键同时按其他。如/键。
	
	2)View与调试debug
	打个断点,程序上选择bebug  as run ,出来调试窗口-->选中变量,点右键->Watch.
	想回去写程序,在右上角选择java视图。
	Window->show view->other可以调试视图。

	3)配置编译和运行java版本。
	点window-->点击Preferences-->Java-->Compiler(编译器)。有java版本。编译时版本。
	Java->Installed JREs(java运行版本) 。运行时版本。
	用高版本的jdk编译出来的程序,用低版本不能运行。
	高版本的jre可以运行低版本jdk编译出来的java程序。
*/
/*
可变参数
	特点:放在未尾。
	三点...位于变量类型和变量名之间时,前后有无空格都可。
	调用可变参数的方法时,编译器为该可变参数隐含创建一个
	数组,在方法体中以数组的形式访问可变参数。
	public static int getSun(int x,int ... args){
		int sum = x;
		for(int i=0;i<args.length;i++){
			sum += args[i];
		}
		return sum;
	}
	面试题。overload与override 的区别.



基本数据类型的自动装箱和拆箱
	自动装箱
	Integer num = 12;
	自动拆箱
	System.out.println(num+10);

	基本数据类型的对象缓存。
	Integer num1 = 12;
	Integer num2 = 12;
	System.out.println(num1==num2);//true
	//基本类型整数在(-128~127)之间,就不创建新对象,大于区间就创建。
	//享元模式。
	Integer num1 = 129;
	Integer num2 = 129;
	System.out.println(num1==num2);//false

	Integer num1 = Integer.valueOf(12);
	Integer num2 = Integer.valueOf(12);
	System.out.println(num1==num2);//true,大于127同样false.
*/
/*
枚举:
	枚举的作用介绍。jdk1.5新特性。
	枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个。否则,
	编译器会报错。这个值在编译时期就被控制。
*/

public abstract class WeekDay1 {

	/**普通类模拟枚举
	 * @param args
	 */
	private WeekDay1(){};//让别人创建不了对象
	public static final WeekDay1 SUN = new WeekDay1() {
		@Override
		public WeekDay1 nextDay() {
			// TODO Auto-generated method stub
			return MON;
		}	
	};
	public static final WeekDay1 MON = new WeekDay1() {
		@Override
		public WeekDay1 nextDay() {
			// TODO Auto-generated method stub
			return SUN;
		}
	};
	
	/*public WeekDay nextDay(){//独立方法去写
		if(this == SUN){
			return MON;
		}else{
			return SUN;
		}
	}*/
	public abstract WeekDay1 nextDay();//让别人实现它。
	
	public String toString(){
		return this == SUN?"SUN":"MON";
	}
}


public class EnumTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		WeekDay1 weekDay = WeekDay1.MON;
		System.out.println(weekDay.nextDay());
		
		WeekDay weekDay2 = WeekDay.FRI;
		System.out.println(weekDay2);
		System.out.println(weekDay2.name());
		System.out.println(weekDay2.ordinal());
		System.out.println(WeekDay.valueOf("SUN").toString());
		System.out.println(WeekDay.values().length);
	}
	
	public enum WeekDay {
		SUN(1),MON,TUE,WED,THI,FRI,SAT;//分号,所有其他信息都必须列于元素列表之后。
		private WeekDay() {//枚举的构造方法必须私有。
			System.out.println("frist");
		}
		private WeekDay(int day) {
			System.out.println("second");
		}
	}	
}
/*枚举就是一个类,枚举的成员就是静态成员。
	//所有其他信息都必须列于元素列表之后。
	//枚举的构造方法必须私有。
	//枚举的成员相当于一个类的实例对象。对象之间用,号隔开
	SUN(1)相当于创建元素用哪个构造方法。
	SUN,SUN():调用空的。

	实现带抽象方法的枚举.

	如果枚举只有一个成员,那可以了解为单例设计模式。

*/

	public enum TrafficLamp {
		RED(30){

			@Override
			public TrafficLamp nextLamp() {
				// TODO Auto-generated method stub
				return GREEN;
			}
		},
		GREEN(45){

			@Override
			public TrafficLamp nextLamp() {
				// TODO Auto-generated method stub
				return YELLOW;
			}},
		YELLOW(5){

			@Override
			public TrafficLamp nextLamp() {
				// TODO Auto-generated method stub
				return RED;
			}
		},
		public abstract TrafficLamp nextLamp();//抽象方法,那么每个成员都要实现。
		private int time;
		private TrafficLamp(int time){this.time = time;}
	}

/*反射的基石->Class类 jdk1.2
Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class.
	对比。众多的人用一个什么类表示?众多的Java类用一个什么类表示。
	人——>Person		Person p1 = new Person();Person p2 = new Person();
	java类-->Class	Class cls1 = ?;没有构造方法,或方法是私有的,不能直接new.
如何得到各个字节码对应的实例对象(Class类型)
	内存中的每份字节码,就是对应的实例对象。通过对象拿字节码。p1.getClass();
	还有一个方法得到类的字节码,Class类的静态方法:Class.forName("java.lang.String");
如何得到各个字节码对应的实例对象(Class类型)
三种:类名.class,如:System.class
	对象.getClass()如:new Date().getClass();
	Class.forName("类名"),如:Class.forName("java.util.Date");
反射主要用第三种,因为在写程序时还不知道类的名字.

九个预定义Class实例对象。
八个基本类型:boolean,byte,char,short,int,long,float,double.
还有一个void.
	int.class.isPrimitive();//是否是原始类型。
	int.class = Integer.TYPE;
	Integer.TYPE;代表基本类型。
	注意:int.class == Integer.class;//不是一个。

	数组类型的实例变量
	int[].class.isPerimitive();//不是
	Class.isArray();//判断是否是数组。字节码。isArray();

	总之:只要在源程序中出现的类型,都有各自的Class实例对象。例如:int[]...
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(int.class == Integer.class);//不相等
		System.out.println(int.class == Integer.TYPE);//相等
		System.out.println(int[].class.isPrimitive());//不是原始
		System.out.println(int[].class.isArray());//是数组
	}
*/
/*
反射:总之:反射就是把Java类中的各种成分映射成相应的java类。

Constructor 类(构造函数的反射)
	
	得到某个类中的所有的构造方法。
	例子;ConStructor [] cons = Class.forName("java.lang.String").getConstructors();
	得到某一个构造方法:
	ConStructor constructor1 = Class.forName("java.lang.String").getConstructor(StringBuffered.class);
	拿到构造方法后,就可以去构造一个实例对象。
	String str2 = (String)constructor1.newInstance(new StringBuffer("abc"));
	//程序编译时不知道是哪个构造方法的,只有运行时才知道。(String).
	//获得方法时要用到类型.class,使用方法时要用到相应类型的对象。
		clazz.newInstance(),运行空构造方法,得到一对象。

		Class clazz = Class.forName("java.lang.String");//拿字节码
		Constructor con = clazz.getConstructor(StringBuffer.class);//拿某一个构造函数
		String str = (String)con.newInstance(new StringBuffer("abc"));//要传对应的sb,不能是("abc")
		System.out.println(str);
*/

import java.lang.reflect.Constructor;
public class RefPointDemo {
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		/*暴力反射私有的构造函数*/
		Class clazz = new RefPoint().getClass();
		Constructor con = clazz.getDeclaredConstructor(int.class,int.class);//Declared是所有的,包括私有。
		con.setAccessible(true);//设为可使用。
		RefPoint refpoint = (RefPoint)con.newInstance(5,6);
		System.out.println(refpoint);
	}
}
 class RefPoint {

	public static int x ;
	private static int y;
	public RefPoint(){}
	private RefPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	public String toString()
	{
		return "x:"+x+",y:"+y;
	}
}
/*
Field类:(成员变量的反射)
	main()...{
		RefPoint ref1 = new RefPoint(3,5);
		Class clazz = ref1.getClass();
		Field fi = clazz.getDeclaredField("y");//私有的成员y就要用这个方法。
		fi.setAccessible(true);//私有的成员y必须为可见
		int yy =(Integer)fi.get(ref1);//这里才具体到哪个对象一个值
		System.out.println(yy);
	}
*/

import java.lang.reflect.Field;
//将任意一个对象中的所有String类型的成员变量所对应字符串内容中的"b"改成"a"。
public class RefFileTest {
	public static void main(String[] args) throws Exception {
		StringSSS sss = new StringSSS();
		show(sss);
		System.out.println(sss);
	}
	public static void show(Object obj) throws Exception{
		Class clazz = obj.getClass();
		Field[] field = clazz.getDeclaredFields();
		for(Field fi:field){
			if(fi.getType()==String.class){//获取成员的类型,同一个类型判断用==.
				String oldstr = (String)fi.get(obj);//如果是String,就传入对象,拿到具体的值
				String newstr = oldstr.replace('b', 'a');//替换b->a.
				fi.set(obj,newstr);//再设置到原对象上。
			}
		}
	}
}
class StringSSS{
	public String str1 = "ball";
	public static  String str2 = "baskball";//静态可以被修改,final修饰后常量不可以。
	public String str3 = "itcast";
	public String toString(){
		return "Str1:"+str1+",Str2:"+str2+",Str3:"+str3;
	}
}
/*以前老师不是讲String一初始化,值就不可以改变吗?
使用反射,没有改变引用地址,也可以改变它的值???*/

/*
Method类。
	代表某一类中的成员方法。
	invoke(str1,1),如果str1为null,那么为静态方法,不需要对象来调用的。
	Method methodChatAt = String.class.getMethod("chatAt",int.class);
	因为一个类中的方法有很多,得到具体的方法用到(方法名,XX),而这个方法有可能被重载,
	所以要用到参数列表的字节码,综合就是(方法名,参数.class);就是得到具体哪个方法。
	再调用这个方法。methodChatAt.invoke(str1,1);str1表示作用的某个对象。
*/
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		String str = "abc";
		Method method = String.class.getMethod("charAt",int.class);//拿到某个方法
		Character ch = (Character)method.invoke(str, 1);//这里可以是(Character),不可以是char???返回的Object不能转变char?
		System.out.println(method.invoke(str, 1));//str表示作用的某个对象,为null时表示为静态方法。不需要对象调用。
		System.out.println(ch+".....");//1.4版本前,invoke(str, 1))写为invoke(str, new Object[]{1}).传入Object数组
	}
	
/*练习,自己写程序,调用人家的main()方法,用反射方式。
	为什么要用反射的方式去调?
	写程序时不知道要执行哪个类的,传入参数才知道要调用哪个。 

	1.5因为兼容1.4,所以传入(null,new String("111","333","222"))这时会打开数组,参数就不对了
	应该改成(null,new Object[]{(new String[]{"111","333","222"})}),先打好包,解开后还是我想要传的.
	还可以这样做,直接告诉编译器,我就是传给了你一个对象。(null,(Object)new String[]{"111","333","222"})
	告诉它不要拆了。
*/

public class MethodDemo {

	public static void main(String[] args) throws Exception {	
		//new MethodSSS().main(new String[]{"111","222","333"});//没用反射,我们一般都是这样调用,
		
		//使用反射怎么调用呢?通过参数传入我想要运行哪个类的主函数。
		Method startMethod = Class.forName(args[0]).getMethod("main", String[].class);
		startMethod.invoke(null,(Object)new String[]{"111","222","333"});//数组参数这里要打包。
	
	}
}
class MethodSSS{
	public static void main(String[] args){
		for(int x=0;x<args.length;x++){
			System.out.println(args[x]);
		}
	}
}

/*
数组的反射,
	具有相同的元素类型的同维数组的字节码是同一个。可以相等==.

	基本数据类型不是Object.所以在Arrays.asList()时,基本数据类型转换时,是将整个
	数组转换成的,因为一个基本数据类型,不能转换成Object.如int

	调用Arrays.asList()时,高版本满足低版本,所以jdk1.4时,asList(Object[] obj),参数,不符合
	就返回用1.5方法,变成可变参数asList(T...a);

*/	main(){
		int[] a1 = new int[3];
		int[] a2 = new int[4];
		String[] a3 = new String[]{"1","2","3"};
		int[][] a4 = new int[3][4];
		
		System.out.println(a1.getClass()==a2.getClass());//true
		//System.out.println(a1.getClass()==a3.getClass());//错误
		//System.out.println(a1.getClass()==a4.getClass());//错误
		System.out.println(a1.getClass().getName());//[I
		System.out.println(a1.getClass().getSuperclass().getName());//java.lang.Object
		System.out.println(a3.getClass().getSuperclass().getName());//java.lang.Object
		
		Object ab1 = a1;
		Object ab2 = a3;
		Object ab3 = a4;
		Object[] ab4 = a1;//只有这个提示报错,说明int不能转成Object
		Object[] ab6 = a3;
		Object[] ab5 = a4;
		System.out.println(Arrays.asList(a1));//[[I@15ff48b]
		System.out.println(Arrays.asList(a3));//{1,2,3}
	}

//数组反射的应用。
	main(){
		//printObj(a3+"...");
		printObj(a3);//这样可以打印
		printObj("xyz");
		
	}
	public static void printObj(Object obj){
		Class clazz = obj.getClass();
		if(clazz.isArray()){//拿到字节码判断是不是数组
			int len = Array.getLength(obj);//拿到数组长度
			for(int x=0;x<len;x++){
				System.out.println(Array.get(obj, x));//[Ljava.lang.String;@affc70...为什么我的打不出来???
														//因为我在上面加了...,printObj(a3+"...");
			}
		}else{
			System.out.println(obj);
		}
	}

/*
	ArrayList集合和HashSet集合,HashCode()分析。
	ArrayList集合,是有顺序的,判断相同与否的依据是:对象的equals()方法,默认比较的是地址值,要想相等,就要重写equals()方法。
	HashSet集合:是无序的,判断的依据是Hashcode(),相同再比较equals().

	HashCode()值,让具备HashCode存储的对象,在内在中对应相应的Hash区域。
	当HashCode依据的算法存储进内存后,就不要修改算法依据的相应的值了。
	因为一改了之后,HashCode()的值也会改变。会内存泄露。
	内存泄露:对象使用后,没有被释放。
	父类引用Collection 分别建立ArrayList,HashSet子类对象,比较它的区别。如元素的大小。
	复写各方法,可发现不同。
*/

/*
	反射的作用->实现框架功能。
	前面已经小小使用一回了,就是输入名字,运行它的主函数。

	框架要解决的核心问题。
	因为在写程序时无法知道要被调用的类名,所以在程序中无法直接用new某个类的实例对象了。
	要用反射方式来做。
*/
public class RefTest {

	/**利用反射实现一个小框架,
	 * 在一个文件中写入内容。config.txt,className = java.util.ArrayList 
	 * @getRealPath();javaweb开发时,可以得到文件的路径。实际开发一定要完整的路径。InputStream("config.txt");
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		InputStream ips = new FileInputStream("config.txt");//读取文件,实际开发要用到绝对路径
		Properties prop = new Properties();
		prop.load(ips);//文件载入内存
		ips.close();
		String className = prop.getProperty("className");//得到文件名字
		Class clazz = Class.forName(className);
		//Constructor con = clazz.getConstructor();//得到构造函数
		//Collection coll = (Collection)con.newInstance();//创建对象
		Collection coll = (Collection)clazz.newInstance();//空的构造方法直接这样。
	}
}
/*
用类加载器的方式管理资源和配置文件。
原理:程序要运行,要加载.class文件,用什么加载这个文件呢?那就是类加载器,
它能够加载.class文件,为什么就不能加载普通文件呢?肯定能。
实例对象.getClass().getClassLoader().getResourceAsStream(cn/itcast/day1/config.txt);注意cn前不加/
文件在src目录下的。java文件,一保存eclipse就会自动编译到bin目录下去,非.java会拷贝过去。
.getResourceAsStream()这个方法只读,又读又写,还是用上面那种。InputStream ips = new FileInputStream("config.txt")。

.getClass().getClassLoader().getResourceAsStream()这种方法加载麻烦,那么.class有没有直接加载的方法呢?
.getClass().getResourceAsStream("resources/文件名")相对路径,当最前面有/时,要用绝对路径,这是用字节码的简单直接方法
加载文件,实际上还是用的类加载器加载实现的。
*/
/*
由内省引出的JavaBean的讲解。
	内省->IntroSpector.-->主要用于对JavaBean进行操作
	什么是JavaBean,特殊的java类,方法按特殊的规定起名。
	例如有个age属性,有方法 int getAge(); void setAge(int age).
	JavaBean也是一个java类,可以进行java类的所有普通操作。
	1.int getAge();没有参数,返回值是int
	2.void setAge(int age)。有参数,返回值是void
	有这二个条件就可以当作JavaBean操作了
*/
class Person
{
	private int x;
	public int getAge()//public
	{
		return x;
	}
	public void setAge(int age)
	{
		this.x = age;
	}
}
/*
上面的Person类当作普通的java类来看,有一个x的成员属性。
Person类当作一个JavaBean 来看,有一个Age属性。
Age-->age如果第二个字母是小的,把第一个字母变成小的。
gettime-->time;
settime-->time
getCPU-->CPU,为了整洁。不是cPU

当JavaBean处理,可以更方便,简单。
	在Java EE开发中,很多环境就要求按照JavaBean方式进行操作。
	JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。
*/

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//对javabean的简单操作,获取属性。
public class JavaBeanDemo {

	public static void main(String[] args) throws Exception {
		Point p1 = new Point(3,5);
		
		String propertyName = "x";
		//普通方式:"x"->"X"->"getX"->MethodGetX-->x获取过程麻烦
		
		//1.得到名称为propertyName的内省。
		Object retVal = getProperty(p1, propertyName);//这里用了方法抽取
		System.out.println(retVal);
		
		Object obj = 7;
		
		setProperty(p1, propertyName, obj);
		 
		 //Object retVal2 = methodGetX.invoke(p1);
		 
		 System.out.println(p1.getX());//当作普通类来获取
		//System.out.println(retVal2);
	}

	private static void setProperty(Object p1, String propertyName, Object obj)
			throws Exception{
		PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,//这是名称
				p1.getClass());//
		Method methodSetX = pd2.getWriteMethod();
		 methodSetX.invoke(p1, obj);
	}

	private static Object getProperty(Object p1, String propertyName)
			throws Exception {
		PropertyDescriptor pd = new PropertyDescriptor(propertyName,//这是名称
				p1.getClass());//得到javaBean属性,得到哪个对象的内省。
		
		//2.下面就可以得到它的读的方法。
		Method methodGetX = pd.getReadMethod();//这里就是得到x的方法。
		
		//3.应用在哪个对象上,没有参数后面就不写.第2,3步就是反射。
		Object retVal = methodGetX.invoke(p1);
		return retVal;//简单方法
	}
}
class Point{
	Point(int x,int y){
		this.x = x;
		this.y = y;
	}
	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;
	}
	private int x;
	private int y;
}

/*下面这个内省的复杂方法。为什么要看?程序设计中经常用这种思想。
在程序中把一个类当作JavaBean来看,就是调用IntroSpector.getBeanInfo方法,
得到的是Beaninfo对象封装了把这个类当作javaBean看的结果信息。
*/	private static Object getProperty(XY xy, String name)
			throws IntrospectionException, IllegalAccessException,
			InvocationTargetException {
		/*
		 * PropertyDescriptor pd = new PropertyDescriptor(name,xy.getClass());
		
		Method methodGetX = pd.getReadMethod();
		Object retVal = methodGetX.invoke(xy);
		return retVal//;简单方法
		*/
		BeanInfo bfs = Introspector.getBeanInfo(xy.getClass());//记住这个Introspector类名
		PropertyDescriptor[] pds = bfs.getPropertyDescriptors();//所有属性信息
		Object retVal = null;
		for(PropertyDescriptor pd:pds){
			if(pd.getName().equals(name)){//名字相同,找到了。
				Method methodGetX = pd.getReadMethod();
				retVal = methodGetX.invoke(xy);
			}
		}
		return retVal;//复杂方法
	}

	/*
	使用工具操作javaBean
先去网上下载工具包JavaBean包,解压。

然后把工具包的.jar文件,加到我们的java工程中来。
局限方法:右击工程名,Build Path-->Configure Build Path-->Libraries->Add  External JARS.
这种方法不会随着工程转换。换了电脑就运行不了。

下面这种方法是放到工程里面转移。
在工程下建立一个目录,lib文件夹,然后把刚才的.jar拷贝进来lib。
然后选择.jar文件,Build Path-->Add to Build Path.前面的图标会变成小奶瓶。

Utils怎么应用呢?
里面有静态方法。
BeanUtils.getProperty(pt1,"x");会有错。没有日志包。
把日志包的.jar也增加到Build Path.再运行。就可以了。
set,get这里都是用字符串操作的,因为web上的数据都是用字符串传送的。

对比另外一个类的静态方法,就是用int操作。如下。
PropertyUtils.setProperty(pt1,"x",9),这个是用属性本身的类型进行操作。

javaBean 可以和Map相互转换。Utils工具有这样的方法。

java7里面,map对象可以这样定义。
Map map = (name:"zxx",age:18);


*/

android培训java培训、期待与您交流!
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值