----------android培训、java培训、期待与您交流! ----------
1、Eclipse使用技巧
Workspace与project
切换工作空间:File---Switch Workspace---Other
一个工作间包含多个工程,切换工作间之后,会影响里面的工程,例如快捷键什么的都要重新配置,如果重新配了之后快捷键还没有用就要考虑下那个快捷键是不是冲突了。
试图管理与程序调试,可以通过Window---Show View来添加各种透视图。
调试程序的时候可以在代码右边双击,然后选择Debugs As,就会弹出Debug的透视图,然后选择要查看的变量,右键选择watch即可。
设置单个工程的javac与java。
高版本的java能否运行低版本的javac编译的程序?能
低版本的java能否运行高版本的javac编译的程序?不能
运行版本(java)比编译版本低(javac)的话不能运行会出现"Bad version number in.class file"问题
总之能设置整个workspace的javac与java,也能设置单个工程的javac与java。
快捷键的绑定与代码模板
新建模板步骤:选择代码---右键Surround With---Configure Template---new...
利用快捷键提高工作效率,导别人的包的时候,别人编写代码的时候的jre可能和你机器上的不一样所以要把原来的给删掉,换成自己的JDK版本
步骤:选中工程---右键选择Build Path---Configure Build Path---Libraries---remove掉,然后再按这个步骤选Add library---JRE System library。
2、静态导入
使用静态导入的好处:提高编写代码的效率。
静态成员的使用,使用import static 引入静态成员。
很简单的东西,看一个例子:
没有静态导入
Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
有了静态导入
import static java.lang.Math.*;
sqrt(pow(x, 2) + pow(y, 2));
其中import static java.lang.Math.*;就是静态导入的语法,它的意思是导入Math类中的所有static方法和属性。
这样我们在使用这些方法和属性时就不必写类名。
3、可变参数
减少代码量,方便输入
如果有多个参数,可变参数要定义在最后边..
位于变量类型和变量名之间,前后有无空格都可以;
在调用可变参数的方法时,编译器会为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
public static void main(String[] args)
{
System.out.println(add(1, 5, 7));
System.out.println(add(2,5));
}
//可变参数 args
public static int add(int x,int...args)
{
int sum=x;
for(int i=0;i<args.length;i++)
{
sum +=args[i];//操作可变参数时把它当数组来用
}
return sum;
}
4、增强for循环
for ( type 变量名:集合变量名 ) { … }
注意事项:
迭代变量必须在( )中定义!
集合变量可以是数组或实现了Iterable接口的集合类
public static int add(int x,int ...args)
{
int sum = x;
for(int arg:args)
{
sum += arg;
}
return sum;
}
5、基本数据类型的自动装箱和拆箱
自动封箱解箱只在必要的时候才进行。还有其它选择就用其它的
自动装箱:Integer num = 12;
自动拆箱:Int num = new Integer(12);
基本Boolean/Byte/Integer(数值范围:-128至127)数据类型的对象缓存:
Integer num1 = 12;
Integer num2 = 12;
System.out.println(num1 == num2);结果为true
Integer num3 = 129;
Integer num4 = 129;
System.out.println(num3 == num4);结果为false
因为数值范围在:(-128至127)数据类型的对象缓存。
在(-128-127)之间的数一旦包装称Integer对象,就会缓存起来,在下次又要使用Integer对象时,就会直接调用,这个简单的方法就是享元模式;
享元模式:就是把很多很小属性相同的元素分装到一个对象中;
简单类型和封装类型之间的差别
封装类可以等于null ,避免数字得0时的二义性。
Integer i=null;
int ii=i; 会抛出NullException 异常。
相当于 int ii=i.intValue();
6、枚举
枚举就相当于一个类,其中也可以定义构造方法、成员变量、普通方法和抽象方法。他就是让某个类型的变量取值只能为若干个固定值中的一个,否则编译器就会报错,同时也可以使编译器在编译的时候就控制填写的非法值,普通变量的方式在开发阶段无法完成这一目标。
枚举是一个特殊的类,每个元素都是这个枚举类的实例对象,它里面可以有也可以定义构造方法、成员变量、普通方法和抽象方法。但是枚举类里面的构造函数必须是私有的,因为你不私有的话别人就能创建对象,那就违背了用枚举的目的了,然后枚举类里面的元素要放在最前面,并且后面加分号。可以通过内部类的方法实现枚举类里面的抽象函数。然后当枚举类中就一个元素时,它就是单例。
public class EnumTest {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
WeekDay weekday = WeekDay.SUN;
System.out.println(weekday.nextDay());
WeekDay2 weekday2 = WeekDay2.SUN;
System.out.println(weekday2.nextday());
TrafficLemp lemp = TrafficLemp.RED;
System.out.println(lemp.nextLemp());
}
public enum WeekDay2{
SUN(2){
public WeekDay2 nextday(){
return MON;
}
},
MON(){
public WeekDay2 nextday(){
return MON;
}
};
// TUD,WED,THI,FRT,SAT;
private WeekDay2(){System.out.println("first");}
private WeekDay2(int time){System.out.println("secord");}
public abstract WeekDay2 nextday();
}
public enum TrafficLemp{
RED(30){
@Override
public TrafficLemp nextLemp() throws InterruptedException {
// TODO Auto-generated method stub
Thread.sleep(3000);
return GREADD;
}
},
GREADD(45){
@Override
public TrafficLemp nextLemp() {
// TODO Auto-generated method stub
return null;
}
},
YELLOW(5){
@Override
public TrafficLemp nextLemp() {
// TODO Auto-generated method stub
return null;
}
};
public abstract TrafficLemp nextLemp() throws InterruptedException;
private int time;
private TrafficLemp(int time){
}
}
}
7、反射
反射就把java类中的各种成分映射成相应的java类
反射的基石—>Class类
Java程序中的各个java类属于同一类事物,描述这一事物的java类名就是Class。就好比众多的人用Person表示,那么众多的java类就用Class表示。对应各个类在内存中的字节码,例如,Person类的字节码,ArrayList类的字节码,等等。
一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型。
获得各个字节码的实例对象的方法:
String str = "abc";
System.out.println(String.class);
System.out.println(str.getClass());
System.out.println(Class.forName("java.lang.String"));
System.out.println(int.class.isPrimitive());//检测原始类型
System.out.println(int.class == Integer.class);
System.out.println(int[].class.isArray());
主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中:
公共类ReflectPoint
public class ReflectPoint {
private int x ;
public int y;
public String str1 = "ball";
public String str2 = "base";
public String str3 = "case";
public ReflectPoint(int x,int y){
this.x = x;
this.y = y;
}
public int getX(int x){
return x;
}
public void getname(){
System.out.println("*****");
}
@Override
public String toString() {
return str1+":"+str2+":"+str3;
}
}
(1)、Constructor 类:代表类的构造方法。
public static void ConstructorTest() throws Exception {
Constructor<String> constructor = String.class.getConstructor(StringBuffer.class);//获取对象的字节码
String str = constructor.newInstance(new StringBuffer("abc"));//创建实例对象
System.out.println(str);
Constructor<ReflectPoint> constructor1 = ReflectPoint.class.getConstructor(int.class,int.class);//获取公共类(ReflectPoint)的字节码
ReflectPoint RP = constructor1.newInstance(5,9);//创建实例对象
System.out.println(RP.getX(6));
}
(2)Field 类:代表类的成员变量(成员变量也称为类的属性)
public static void FieldTest(Object obj) throws Exception{
Field fieldY = obj.getClass().getField("y");//通过字节码获取其中的成员变量
System.out.println(fieldY.get(obj));
Field fieldX = obj.getClass().getDeclaredField("x");//通过字节码获取其中的成员变量
fieldX.setAccessible(true);//原方法为私有的,设置为可以访问
System.out.println(fieldX.get(obj));
}
(3)Method类:代表类的方法。
public static void MethodTest(Object obj) throws Exception{
//获取字节码文件中的某个特定的方法getMethod(方法名, 参数类型.class)
Method method = obj.getClass().getMethod("getX", int.class);
//invoke方法前面是哪个对象在调用反射出来的那个方法,如果对象为空的话,那说
//明不能被对象调用,那这个方法就是静态方法了
System.out.println(method.invoke(obj, 7));
Method method1 = obj.getClass().getMethod("getname");
System.out.println(method1.invoke(obj));
}
(4)Array类:提供了动态创建数组,以及访问数组的元素的静态方法。
数组的反射:具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象。
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());true System.out.println(a1.getClass() == a4.getClass());false System.out.println(a1.getClass() == a3.getClass());false Object aObj1 = a1; Object aObj2 = a4; Object[] aObj4 = a3; Object[] aObj5 = a4;
代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。
基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用;
非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
Arrays.asList()方法处理int[]和String[]时的差异。
处理int[]时打印的是数组名和哈希值,处理S特ring[]时打印出来的是数组里面的元素。
就是集合里面装的是对象,那int[]数组转换为集合后不可能数组里面的元素就是集合里面的元素,
因为数组里面的是int型值不是对象,而String数组里面的字符串本来就是一个对象,所以转换为
集合后可以打印出来。
8.HashCode的分析
hashcode方法返回该对象的哈希码值。
hashCode()方法可以用来来提高Map里面的搜索效率的,Map会根据不同的hashCode()来放在不同的位置,Map在搜索一个对象的时候先通过hashCode()找到相应的位置,然后再根据equals()方法判断这个位置上的对象与当前要插入的对象是不是同一个。
所以,Java对于eqauls方法和hashCode方法是这样规定的:
1、如果两个对象相同,那么它们的hashCode值一定要相同;
2、如果两个对象的hashCode相同,它们并不一定相同
上面说的对象相同指的是用eqauls方法比较。
要正确的实现Map里面查找元素必须满足一下两个条件:
(1)当obj1.equals(obj2)为true时obj1.hashCode() == obj2.hashCode()必须为true
(2)当obj1.hashCode() == obj2.hashCode()为false时obj.equals(obj2)必须为false
加入有这样一种情况,现在有个数组,这个数组中有1000个元素,这些元素都是不相同的,你现在要再向里面插入一个元素,如果你现在只有equals方法,那么你就得比较1000次,但是你现在有了hashcode,你只需要将新元素通过hashcode,得到一个值,然后将这个新元素与原来1000个元素中hashcode相等的元素进行equal(这时你equal的次数远远比1000次小的多),如果equal出有相等的,那么就说明这1000个中已经有与新元素相等的元素了。先使用hashcode,再使用equal,将大大优化执行效率!
9.反射的作用和实现框架功能
框架和工具类不同,框架是调用者,工具类是被调用者
框架要解决的核心问题
我在写框架时,你这个用户可能还在上小学,还不会写程序呢?我写的框架程序怎样能调用到你以后写的类(呢?因为在写才程序时无法知道要被调用的类名,所以,在程序中无法直接new某个类的实例对象了,而要用反射方式来做。我们可以用一个类来写配置文件,写的时候通过反射配置文件的获得相应的类名,然后用户拿到框架的时候只需要把类名写到配置文件中就可以使用整个框架了。
1,配置文件放在哪里,在实际开发中没有用相对路径这样写的配置文件的,如:
InputStream isp = new FileInputStream("config.properties");
最好用getRealPath();方法 不管用户安装到那个目录下都能获取到它所在的位置。一定要记住用完整的路径,但完整的路径不是硬编码,而是运算出来的。
2.每一个.class文件,我们在用它的时候都要把他加载到内存来,用到类加载器。
ReflectTest2.class.getClassLoader().getResourceAsStream("配置文件");
这个方法的意思是在classpath指定的那些目录下逐一的去查找要加载的文件。
这种方式只能读。无论是相对路径还是绝对路径,内部调用的都是getClassLoader();
eclipse会源程序目录下的所有的.java文件自动编译成、class文件,保存的时候就编译了,并且放到classpath指定的目录下去,而把非.java的文件原封不动的搬到那个目录。