一、开发工具
01、Eclipse和MyEclipse的关系:03.eclipse工程管理与快捷键配置
(1) MyEclipse是Eclipse的一个插件,不过有的厂商把MyEclipse和Eclipse打包在一起。
02、MyEclipse
(1)编译和运行时所用的版本尽可能相同,高版本的java可以运行低版本的javc。
(2)每个工作间都有自己独立的配置。一个工作间包含多个工程,一个工作间的设置影响这个工作间下的所有工程,而不影响其它工作间。
(3)透视图包含了几个小窗口组成的一个大的工作窗口。透视图是小窗口的集合。
(4)命名规则一般的公司网址倒过来写如cn.itcaats.然后加自己的工作包,如去华为公司面试可写成,cn.itcast.interview.
(5)设置单个工程的javac和java,只要选择那个工程然后右键选择首选项即可。
(6)自定义快捷键和模板可提高编程效率。
(7)导入工程:先复制工程到工作间导入。导入的时候还要注意JDK是否与当前环境兼容。
二、java5的一些简单新特性
03.java5的静态导入
也就是把一个类的静态方法或变量导入(import staticjava.lang.Math.*;),便成为当前类的方法而可直接调用。
04.可变参数,就是一个方法的参数个数不固定。
(1)只能出现在参数列表的最后;
(2)…位于变量类型和变量名之间,前后有无空格都可以;
(3)调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数,固定的不属于数组元素。
(4)实现例子:求参数总和class VarableParaeter
{
public static void main(String[] args)
{
System.out.println(add(2,3));
System.out.println(add(2,3,5,6,7,8));
}
public static int add(int x,int… args)
{
int sum=x;
for(int i =0;i<args.length;i++)
{
sum+=args[i];
}
return sum;
}
}
05.java5的增强for循环
for(type 变量名:集合变量名){...}
注意事项:
(1)迭代变量必须在()中定义。
(2)集合变量可以是数组或实现了iterable接口的集合类
例子:
public static int add(int x,int… args)
{
int sum=x;
for(int arg:arfs)
{
sum+=arg;
}
return sum;
}
06.基本数据的自动拆装箱及享元设计模式
(1)例子:
class AutoBox
{
public static void main(String[] args)
{
//自动的把基本数据类型转成Integr并赋给obj,这就是自动装箱。
Integr iobj = 3;
//自动的Integr类型的iobj转成int类型进行运算,这就是拆箱。
System.out.println(iobj + 12);
}
}
对于int整数要装箱成Integer整数的时候如果大小在一个字节之内(-128~127),一旦包装成一个Integer对象之后就会缓存,下次如果要装箱成一个Integer对象的时候先看缓存里有没有,有的话就从里面直接拿,这样就节省的内存空间,因为比较小的整数使用的频率会很高,如果一出现一个数就创建一个对象,而且这些整数变化不是很大,密度相对高,就没有必要每个都创建对象造成内存浪费,其他类型数据也是这个道理。这是一种设计模式叫享元模式(flyweight)。
(2)享元模式(flyweight):
有很多个小的对象,它们有很多属性相同,把它们变成一个对象,那些不同的属性把它们变成方法的参数称之为外部状态,那些相同的属性称之为这个对象的内部状态。
三、java5的枚举
07.枚举的作用介绍
(1)为什么要有枚举
—— 问题:要定义星期几或性别的变量,该怎么定义?假设用1-7分别表示星期一到星期日,但有人可能会写成int weekday = 0;
—— 枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则编译器就会报错。可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。
(2)枚举也是一个类,在里面定义的其它东西必须位于元素列表之后,元素列表之后定义东西元素列表末尾要有;结束。
(3)如果定义构造方法不能是public。
(4)里面的元素是静态的,所以加载一个元素时就执行一次无参的构造方法。如果也调用其它的构造方法则在元素的后面用()起来加入元素即可,如 元素(参数) —> SUN(1,2)
(5)如果一个元素后面有一个{}就表示这是一个子类。
(6)枚举可得一个成员时,就可以作为一种单例的实现方式。
08.用普通类模拟枚举的实现原理
09.java5的枚举的基本应用,如下例子
package cn.itcast.day1;
public class EnumTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
UeekDay ueekDay2 = UeekDay.FRI;
System.out.println(ueekDay2);
//获取自己的名字
System.out.println(ueekDay2.name());
//自己的排行第几
System.out.println(ueekDay2.ordinal());
//将传过来的字符串变成一个对应枚举UeekDay的元素
System.out.println(UeekDay.valueOf("SUN".toString()));
//把元素当成一个数组,获取其长度
System.out.println(UeekDay.values().length);
}
public enum UeekDay{
//这是一个子类并调用带一个参数的构造函数
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;}
}
}
四、反射的深入讲解
10.透彻分析反射的基础_Class类
(1)Java程序中的各个Java类属于同一类事物,描述这类囊括的Java类名就是Class。
(2)Class的实例对象是一份内存里的字节码。Class chs1 = Date.class//字节码1;
(3)创建Class时得到一份类的字节码的方式,做反射的时候主要用第三种方法,因为写源程序的时候它不知道类的名字,在运行的时候人家传给一个字符串,这个字符串包含了一个类的名字:
—— 类名.class,例如 System.class
—— 对象.getClass(),例如 new Date().getClass()
——Class.forName("类名"),例如 Class.forName("java.util.Date");
这个方法有两种情况:
第一种:这份字节码曾经被加载过,已经待在java虚拟机里面了。
第二种:java虚拟机里面还没有这份字节码,则用类加载器去加载,把加载进来 的字节码放Java虚拟机里面,以后要得到这份字节码就不用加载了。
(4)八个基本数据类型(boolean、byte、char、short、int、long、float 和 double)对象分别有一个对应Class实例对象和关键字 void 也表示为 Class 对象
(5)isPrimitive()判断是否是原始类型(基本类型)的字节码,isArray()判断是否是数组的字节码。
(6)总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[],void...
(7)例子
package cn.itcast.day1;
public class ReflectTest {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
String str1 = "abc";
//获得String的字节码1
Class cls1 = str1.getClass();
//获得String的字节码2
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");
System.out.println(cls1 == cls2);
System.out.println(cls1 == cls3);
//isPrimitive()判断是否是原始类型(基本类型)的字节码
System.out.println(cls1.isPrimitive());
//int 是基本类型
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());
//isArray()判断是否是数组的字节码
System.out.println(int[].class.isArray());
}
}
11.构造方法的反射应用
(1)得到某个类所有的构造方法(getConstructors()):
Constructor[]constructors=Class.forName("java.lang.String").getConstructors();
(2)得到某一个构造方法(getConstructor(参数)):
Constructor constructor =Class.forName("java.lang.String").getConstructor(StingBuffer.class);
Constructor constructor =Class.forName("java.lang.String").getConstructor(类型.class,类型.class...);
(3) 创建构造函数
通常方式:Stringstr=new String(new StringBuffer("abc"));
反射方式: Stringstr=(String)constructor.newlnstance(new StringBffer("abc"));
调用获得的方法时要用到上面相同类型的实例对象。
12.成员变量的反射
Field创建一个实例时实例不是对象身上的值,而是类上,要用它去取某个对象对应的值
13.成员方法的反射
(1)通常方式:System.out.printkn(str.charAt(1));
(2)反射方式:System.out.println(charAt.invoke(str,1));
如果传递给Method对象的invoke()方法的第一个参数为null,说明该Method对象对应的是一个静态方法!
13. 数组的反射应用
(1)具有相同维数类型的数组属于同一类型,即具有相同的Class实例对象。
(2)代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class、
(3)基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用
非基本类型的一维数组,既可以当作Object类型使用,又可以当作Object[]类型使用。
(4)不用通过数组中的元素知道数组的类型,但可以知道单个元素所对应的类型,如
Object[] a = new Object["a",1];
a[].getClass().getName();
14.ArrayList_HashSet的比较及Hashcode分析
(1)ArrayList:
—— 是一种先后按顺序存储变量引用的一种集合,不考虑是否重复。
(2)Hashet:
—— 存储的时候先根据HashSet算法(不同的内存有不同的HashSet算法)的值判断里面是否有相等的数据,不的话就不再写入(set集合就是这样的,不过省去了算法)
—— HashSet的算法,把集合分成若干下区域,每一个要存进来的对象算成一个值,根据算得的值存入相应的相应的区域,而当我们要查找某个对象时,我们先算出这个的对象的HashSet的值,看他属于哪个区域,然后在那个区域中查找是否存在相等对象,这个性能就大大的提高了。
—— 要想你的对象有这样值的对象,前提是你的数据必须存入HashSet这样的集合中,如果其它集合因为没有HashSet这样的结构,所以没有任何价值。
(3)当一个对象被存储进HashSet集合中以后,就不要修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回 找不到对象的结果,这也会无法从HashSet集合中单独删除当前对象,从而造成内存泄露。
(4) 例子:
package cn.itcast.day1;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
public class ReflectTest1 {
public static void main(String[] args) throws Exception{
String str1 = "abc";
Collection collections = new HashSet();
ReflectPoint p1 = new ReflectPoint(3, 3);
ReflectPoint p2 = new ReflectPoint(5, 5);
ReflectPoint p3 = new ReflectPoint(3, 3);
collections.add(p1);
collections.add(p2);
collections.add(p3);
collections.add(p1);
System.out.println("集合大小:"+collections.size());
ReflectPoint pt1 = new ReflectPoint(3, 5);
Field fieldy = pt1.getClass().getField("y");
//fieldy不是对象身上的值,而是类上,要用它去取某个对象对应的值.get()获取的可见的值
System.out.println(fieldy.get(pt1));
//x是private的,要用getDeclaredField()获取不可见的值
Field fieldx = pt1.getClass().getDeclaredField("x");
//暴力反射(强制访问)
fieldx.setAccessible(true);
System.out.println(fieldx.get(pt1));
changeStringValue(pt1);
System.out.println(pt1);
//str1.charAt();
Method methodCharAt = String.class.getMethod("charAt", int.class);
System.out.println(methodCharAt.invoke(str1, 1));
// TestArguments.main(new String[]{"wgfregh","wfewgrewfg"});
String startingClassName = args[0];
Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class);
/* jdk 1.5为了兼容1.4版本String[]相当于Object[],人家收到一个Object[]数组以后不会把它当作一个参数,
人家会把数组这一包东西打开,打开的东西每一个元素当作一个参数,所以出现参数不匹配。
mainMethod.invoke(null,new String[]{"111","222","333"});
*/
//(解决方案1)传进一个装Object[]里面的一个元素是String[],当自动拆箱出来后每个元素是一个参数,String[]就当作一个参数传递。
mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});
/*(解决方案2)在前面声明这是一个Object类型的一个元素
mainMethod.invoke(null, (Object)new String[]{"111","222","333"});
*/ }
private static void changeStringValue(Object obj)throws Exception {
//创建一个存放变量字节码的数组
Field[] fields = obj.getClass().getFields();
//迭代所有变量的对应字节码
for(Field field : fields){
/* 判断变量的对应字节码是否是String类型,不用
if(field.getType().equals(String.class))
因为是对同一份字节码的比较,应该用==而不用equals
*/ if(field.getType()==String.class){
//获取对应的字节码变量的值
String oldValue = (String)field.get(obj);
//调换值
String newValue = oldValue.replace('b', 'a');
//对field对象进行设值
field.set(obj,newValue);
}
}
}
}
class TestArguments{
public static void main(String[] args){
for(String arg : args){
System.out.println(arg);
}
}
}
class ReflectPoint {
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ReflectPoint other = (ReflectPoint) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
private int x;
public int y;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "itcast";
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
//覆盖方法
public String toString() {
// TODO Auto-generated method stub
return str1 +":"+str2+":"+str3;
}
}
15.由内省引出JavaBean的讲解
(1)IntroSpector(查找)--->JavaBean(方法是由get(没有参数传递)或set打头,并都是public)-->特殊的Java类。
(2)如果一个类中有get或set的方法打头也可以把它当成JavaBean来操作。
(3)一个符合JavaBean特点的类可以当作普通类一样进行使用,但把它当JavaBean用肯定给我们带来一些额外的好处。
(4)JavaBean的好处:
—— 在Java EE开发中,经常要使用到JavaBean,很多环境就要求按JavaBean方式进行操作,别人都 要求那么做,那我们就没有选择的余地。
—— JDK中担供了对JavaBean进行操作的一些API,这套API就称为内省。
(5)属性的特点:
—— 去掉get或set后的名称改成小写-->如果第二字母小的,则把第一个字母变成小的,同理则变成大-->属性名
(6)综合例子
——ReflectPoint.java文件
package cn.itcast.day1.setter;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class IntrospectorTest {
public static void main(String[] args) throws Exception {
javabean2();
}
//用Myeclipse自动生成getter和setter方法
public static void javabean2() throws Exception{
ReflectPoint pt1 =new ReflectPoint(3,5);
String propertyName = "x";
Object retVal = getProperty(pt1, propertyName);
System.out.println(retVal);
Object value = 7;
setProperty(pt1, propertyName, value);
Object retVal2 = getProperty(pt1, propertyName);
System.out.println(retVal2);
}
private static void setProperty(ReflectPoint pt1, String propertyName, Object value)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
/* PropertyDescriptor是属性描述符的类,它的构造函数接收两个参数是(属性名,类(表示要打哪个类当作JavaBean来用))
得到对应类的属性pd*/
PropertyDescriptor pd =new PropertyDescriptor(propertyName , pt1.getClass());
// 得到类中getter方法
Method methodSetX = pd.getWriteMethod();
// 在pt1上调用这个方法,并传递参数
methodSetX.invoke(pt1,value);
}
private static Object getProperty(ReflectPoint pt1, String propertyName)
throws IntrospectionException, IllegalAccessException,
InvocationTargetException {
PropertyDescriptor pd =new PropertyDescriptor(propertyName , pt1.getClass());
Method methodGetX = pd.getReadMethod();
// 在pt1上调用这个方法,并且get不用传递参数,得到一个反回值
Object retVal = methodGetX.invoke(pt1);
return retVal;
}
}
package cn.itcast.day1.setter;
public class ReflectPoint {
private int x;
public int y;
public ReflectPoint(int x, int y) {
super();
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;
}
}
16. 使用BeanUtils工具包操作JavaBean
—— BeanUtils数据传递是以字符串传递。