------- android培训、java培训、期待与您交流! ----------
Eclipse的使用
主要讲述的是Eclipse的操作, JDK1.5的新特性(静态导入 、可变参数、自动装箱拆箱 、增强for循环 、枚举、注解和泛型等),反射,框架,内省,泛型和代理等内容。
Eclipse IDE:--->Itegrity Development Environment
更改工程(项目)名:右键—refactor—rename
注释段落 快捷键:ctrl+shift+/ 效果是:/* */
透视图,Eclipse怎么调试变量:右键—Debug As—选中变量—选watch—在debug透视图里可以看
新开的工作间,设置快捷键:Window—preference—General—Key 如,Alt+/ 是快捷输出Sop
代码模板设置:Window—preference—java—editor—Templates
设置JVM内存的大小: JVM默认的内存大小为64M。
设置JVM内存大小的方法是:在所作的项目上面右键>Run Configurations... >VM arguments,在下面输入如下命令:-Xmx1024m,后面的数字可以根据自己的实际情况来设置(这里设置的大小是1024M,即1G),点击 Run,就行了。
修改Eclipse的编码方式:如果要使新建立工程、java文件直接使UTF-8则需要做以下工作:
1、windows->Preferences...打开"首选项"对话框,左侧导航树,导航到 general->Workspace,右侧Text file encoding,选择Other,改变为UTF-8,以后新建立工程其属性对话框中的Text file encoding即为 UTF-8。
2、windows->Preferences...打开"首选项"对话框,左侧导航树,导航到 general->Content Types,点开Text,选择Java Source File,在下面的Default encoding输入框中输入UTF-8,点Update,则设置Java文件编码为UTF-8。
二:静态导入
1.import语句可以导入一个类或某个包中的多个类
2.import static语句导入一个类中的某个静态方法或所有的静态方法
三:可变参数的特点
1.只能出现在参数列表的最后
2. .....位于变量类型和变量名之间,前后有无空格都可以
3.调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数
eg:public static int(int x,int ...args)
{
int sum-x;
for(int i=0;i<args.length;i++)
{
sum+=args[i];
}
return sum;(args表示参数,为参数数组名)
}
实例:public class Varible {
public static void main(String[] args)
{
// TODO Auto-generated method stub
System.out.println(add(2,3));
System.out.println(add(2,3,5));
}
static int add(int x,int ...args )
{
int sum=x;
/* for (int i = 0; i < args.length; i++)
{
sum+=args[i];
}*/
for (int i : args)
{
sum+=i;
}
return sum;
}
}
四:增强for循环
语法:for(type 变量名:集合变量名){......}
注意事项:1。迭代变量必须在()中定义 2.集合变量可以是数组或实现了Iterable接口的集合类
实例:public static int add(int x,int ...args)
{
int sum-x;
for(int arg:args)
{
sum+=arg;
}
return sum;
}
五:基本数据类型的自动装箱与拆箱
1.自动装箱Integer num1=12 自动把一个基本数据类型装载为I呢个人对象,并赋值给引用变量num1
2.自动拆箱System.out.println(num1+12);
3.基本数据类型的对象缓存:
eg:Integer num1=12; Integer num3=129;
Integer num2=12; Integer num4=129;
System.out.println(num1==num2);
System.out.println(num3==num4);
Integer num5=Integer valueOf(12);
Integer num6=Integer valueOf(12);
System.out.println(num5==num6);
2中的num1为Integer对象不支持加法运算,所以必须先将其转化为基本数据类型,即12,再作加法运算
六:享元模式
如果很多很小的对象有相同的部分,可把他们变成一个对象,对不同的部分,则变为外部方法的参数称为外 部状态,而相同的部分则称为内部状态。
七:枚举
1.为什么要枚举
枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译就会报错。枚举可以让 编译 器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标
2.用普通类如何实现枚举功能,定义一个Weekday的类来模拟枚举功能
2.1:私有的构造方法
2.2:每个元素分别用一个公有的静态成员表示
2.3:可以有若干公有或抽象方法。例如:要提供nextday方法必须是抽象的
3.枚举的格式
WeekDay weekday2=WeekDay.FRI;//表示定义的枚举类变量只能用限定的值给其赋值
System.out.println(weekDay2);
System.out.println(weekDay2.name());
System.out.println(weekDay2.ordinal());
System.out.println(weekDay.valueOf("SUN"));
System.out.println(weekDay.values().length);
System.out.println(weekDay2);
public enum WeekDay
{
System.out.println("first");
}
private weekDay(int day)
{
System.out.println("second");
}
4.枚举就相当于一个类,其中也可以定义构造方法、成员变量、普通方法和抽象方法
5.枚举元素必须位于枚举中的最开始部分,枚举元素的后面有分号与其他元素隔开把枚举中的成员方法或变量等 放在枚举元素的前面,编译器将报错
6.带方法的枚举
6.1.定义枚举TrafficLamp
6.2.实现普通的next方法
6.3.实现抽象的next:每个元素分别是由枚举类的来生成实例对象,这些子类采用类似内部类的方式进行定义
6.4.增加上表示时间的构造方法
7.枚举只有一个成员时,就可以作为一种单例的实现方式
八:反射的基石:Class类
1.java程序中的各个java类属于同一类事物,描述这类事物的java类就是Class
2.class与Class的区别,前者是定义类时所用的关键字,而后者是一个类的名字,代表的是一类事物
Class cls1=Date.class //Date.class为编译后的字节码,实质为一个对象。而Class cls1,Class类的对象 代表内存内的一份字节码,即:可用Class类的对象加载源程序编译后的字节码
3.对象.getClass()方法也可得到该类的字节码
4.Class forName("类名"):作用是返回字节码
两种情况:一.这个类的字节码已加载到内存了,直接找到该字节码并返回
二:java虚拟机中还没有该字节码,就用类加载器加载,并缓存到虚拟机,然后返回该字节码
5.九个预定义Class实例对象:由八种基本数据类型加上void.class形成
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
int.class==Integer.TYPE
数组类型的Class实例对象
Class.isArray();
总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如int[],void
eg:public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
String str1="abc";
Class cls1=str1.getClass();
Class cls2=String.class;
Class cls3=Class.forName("java.lang.String");
System.out.println(cls1==cls2);
System.out.println(cls1==cls3);
System.out.println(cls1.isPrimitive());//判断该字节码是否为基本数据类型
System.out.println(int.class.isPrimitive());
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());
}
九:反射
1.定义:反射就是把java类中的各种成分映射成相应的java类,例如:一个java类中用一个Class类的对象来表 示,一个类中的组成部分:成员变量,方法,构造方法,包等等信息也用一个个的java类来表示,就像汽车是 一个类,汽车中的发动机,变速箱等等也是一个个的类。表示java的Class类显然要提供一系列的方法,来获 取其中的变量,方法,构造函数,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,他们是 Field、Method、Contructor、Package等等
2.一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些 实例对象
十:Constructor类
1.Constructor类代表某个类中的一个构造方法
2.得到某个类所有的构造方法
例子:Constructor constructors[]=Class forName("java.lang.String").getConstructors();
3.得到某一个构造方法:
例子:Constructor constructors=Class forName("java.lang.String").getConstructor (StringBuffer.class);
4.创建实例对象:
通常方式:String str=new String(new StringBuffer("abc"));
反射方式:String str=(String)constructor.newInstance(new StringBuffer("abc");
//调用获得的方法时要用到上面相同类型的实例对象
String.class.getConstructor(StringBuffer.class);
//参数的个数代表返回的构造函数是哪一个
Constructor constructor1=String.class.getConstructor(StringBuffer.class);
//这句话返回一个该传递那种参数的构造方法的实例对象
String str2=(String)constructor1.newInstance(new StringBuffer("abc"));
//这句话表示找到构造方法后,给它传递一个参数,并执行构造方法,将结果转换为字符串型,并赋值
System.out.println(str2.charAt(2));
5.Class.newInstance()方法
例子:String obj=()Class.forName("java.lang.String").newInstance();
该方法的内部先得到默认的构造方法,然后用构造方法创建实例对象
该方法内部用到了缓存机制来保存默认构造方法的实例对象
class->constuctor->new object
十一:Field类
1.Field类代表某个类中的一个成员变量
2.演示用eclipse自动生成java类的构造方法
public class ReflectPoint {
private int x;
public int y;
public ReflectPoint(int x,int y)
{
super();
this.x=x;
this.y=y;
}
}
ReflectPoint pt1=new ReflectPoint(3,5);
Field fieldy=pt1.getClass().getField("y");
//fieldy的值不是5,他不是对象身上的变量,而是类上,要用他去取某个对象对应的值
System.out.println(fieldy.get(pt1));
Field fieldx=pt1.getClass().getDeclaredField("x");//getDeclaredField()方法用于访问私有的字段
fieldx.setAccessible(true);//设置访问性,可访问
System.out.println(fieldx.get(pt1));
private static void changeStringValue(Object obj)throws Exception
{
Field[]fields=obj.getClass().getFields();
for (Field field : fields) {
if(field.getType()==String.class){
String oldvalue=(String)field.get(obj);
String newValue=oldvalue.replace('b','a');
field.set(obj,newValue);
}
}
十二:Method类
1.Method类代表某个类中的一个个成员方法
2.得到类中的某一个方法:
例子:Method charAt=Class.forName("java.lang.String").getMethod("charAt","int.class");
3.调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke(str,1));
如果传递给Method对象的invoke()方法的一个参数为null,说明Method对象对应的是一个静态方法
eg:Method methodCharAt=String.class.getMethod("charAt", int.class);
//表示要取那个方法,以及该方法的参数列表
System.out.println(methodCharAt.invoke(str1, 1));
//表示在那个对象身上调用charAt方法,并传递一个参数执行
十三:用反射方式执行某个类中的main方法
1.目标:写一个程序,该程序能够根据用户提供的类名,去执行该类中的main方法
2.问题:启动java程序的main方法的参数是一个字符串数组,即public static void main(String[]args),通过 反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而 按jdk1.4,数组中的每个元素对应一个参数。
3.解决办法:
mainMethod invoke(null,new Object[](new String[]("xxx")));
mainMethod.invoke(null,(Object)new String[]("xxx"));编译器会作为特殊处理,编译时不把参数当做数组 看待,也就不会将数组打散成若干个参数了
eg: TestArguments.main(new String[]{"111","222","333"});
String startingClassName=args[0];
Method mainMethod=Class.forName(startingClassName).getMethod("main", String[].class);
mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});
/*这一句说明默认是将new String[]{"111","222","333"}这个传递数拆箱为三个参数,即数组的每 一个元素度作为一个参数,加上new Object之后,就是给它打包,将其转化为一个数组,即一个参 数,因为main方法默认传递的是一个字符串数组型的参数*/
mainMethod.invoke(null, (Object)new String[]{"111","222","333"});
//这一句告诉编译器在编译时将new String[]{"111","222","333"};当做一个对象,不拆箱
//数组本来就是object对象的子类,
十四:数组的反射
1.具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象
2.代表数组的Class实例对象的getSuperClass()方法返回的父类为Objcet类对应的Class
3.基本类型的一维数组可以被当做Object类型使用,不能当做Object类型使用,非基本类型的一维数组,既可以
eg: int[]a1=new int[]{1,2,3};
int[]a2=new int[4];
int[][]a3=new int[2][3];
String[]a4=new String[]{"a","b","c"};
System.out.println(a1.getClass() == a2.getClass());
//System.out.println(a1.getClass() == a4.getClass());
//System.out.println(a1.getClass() == a3.getClass());
System.out.println(a1.getClass().getName());
System.out.println(a1.getClass().getSuperclass().getName());
System.out.println(a4.getClass().getSuperclass().getName());
Object aObj1=a1;
Object aObj2=a4;
//Object[]aObj3=a1;这里不能将int[]转化为Object[],一维的数组只能用Object对象名的形式
Object[]aObj4=a3;
Object[]aObj5=a4;
System.out.println(a1);
System.out.println(a4);
System.out.println(Arrays.asList(a1));
System.out.println(Arrays.asList(a4));
//aslist():返回一个受指定数组支持的固定大小的列表。(对返回列表的更改会“直接写”到数组 )此方法同 Collection.toArray() 一起,充当了基于数组的 API 与基于 collection 的 API 之间的桥梁。
private static void printObject(Object obj) {
Class clazz=obj.getClass();
if (clazz.isArray()) {
int len=Array.getLength(obj);
for (int i = 0; i <len; i++) {
System.out.println(Array.get(obj, i));
}
}else{
System.out.println(obj);
}
}
十五:集合HashCode
作用:防止内存泄露
eg:public static void main(String[] args) {
// TODO Auto-generated method stub
//Collection collection=new ArrayList();
Collection collection=new HashSet();用户
ReflectPoint pt1=new ReflectPoint(3, 3);
ReflectPoint pt2=new ReflectPoint(5, 5);
ReflectPoint pt3=new ReflectPoint(3, 3);
collection.add(pt1);
collection.add(pt2);
collection.add(pt3);
collection.add(pt1);
// pt1.y=7;
//此处是防止内存泄露的语句,如果没有这句,则pt1表面上被移走了,而实际上却在内存中
collection.remove(pt1);
System.out.println(collection.size());
}
十六:反射的作用:实现框架功能
1.框架调用用户提供的类,而用户调用工具类
2.getRealPath()的存放路径为配置文件的内部路径,能读写一定要用完整的路径,但完整的路径不是硬编码, 而是运算出来的
3..class文件加载进入内存用类加载器
.class.getClassLoader.getResourceAsStream(name);
4.在.class文件的目录下去查找name文件,name路径最前面不能加/,不用放在classpath目录下
5.InputStream in=ReflectTest2.class.getResourceAsStream("config.properties");//可以用相对或绝对
由.class直接提供方法
总之:配置文件路径由classpath指定,在eclipse环境下放在src目录或src子目录
eg:
InputStream ips=new FileInputStream("config.properties");
Properties props=new Properties();
props.load(ips);
ips.close();
String str=props.getProperty("className");
Collection collections=(Collection)Class.forName(str).newInstance();
//InputStream ips=new FileInputStream("config.properties");
//这里用的是相对路径,但最好是用完整的绝对路径
//InputStream ips=ReflectTest2.class.getClassLoader().getResourceAsStream ("test/oop/Class/config.properties");
InputStream ips=ReflectTest2.class.getResourceAsStream("Resource/config.properties");