Java基础加强总结(1)
2011-10-01 23:06
316 查看
一、做开发时的两个阶段
编译时阶段:写源代码、用javac编译
运行时阶段:运行程序
二、静态导入
import语句可以导入一个类或者某个包中的所有类
import static语句导入一个类中的某个静态方法或所有静态方法
三、可变参数
特点:
1、只能出现在参数列表的最后。
2、...位于变量类型和变量名之间,前后有无空格都可以。
3、调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
四、for循环增强
语法:
for(type 变量名:集合变量名){
}
注意事项:
迭代变量必须在()中定义。
集合变量可以是数组或实现了Iterable接口的集合类
举例:
五、自动装箱与拆箱
六、享元模式
flyweight
如果很多很小的对象,它们有相同的东西,那就可以把它们变成一个对象,把它们不同的东西变成外部的属性,作为方法的参数传入
整数:-128~127 使用的是享元模式
图标显示:i.display(int x,int y);
字符显示i{x,y}
七、枚举
为什么要有枚举?
枚举就是要让某个类型的变量的取值只能为若干个固定值中得一个,否则编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通的变量方式在开发阶段无法实现这一目标。
用普通类如何实现枚举功能,定义一个Weekday的类来模拟枚举功能。
私有的构造方法
每个元素分别用一个公有的静态成员变量表示。
可以有若干公有方法或抽象方法,例如,要提供nextDay方法必须是抽象的。
枚举元素加小括号表示调用它的带参数的构造方法
枚举元素加大括号表示枚举类的子类
八、反射(不是java5的新特性,从Java1.2开始就有)
一个类被加载器加载到内存中,占用一片内存空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以他们在
内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型,就是Class类型。
String.class, new String("abcd").getClass() 都是String类的字节码 是同一个对象
Class.forName("java.lang.String")加载类,得到这个类的字节码
有9个预定义的Class对象:8个基本类型和void
isPrimitive() 判定指定的对象是否表示一个基本类型。
boolean isArray() 判定此 Class 对象是否表示一个数组类。
反射:
反射就是把Java类中的各种成分映射成相应的Java类。例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中得发动机,变速箱等等也是一个个的类。表示Java类的Class类显然要提供一系列的方法,来获得其中变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,他们是Field、Method、Contructor、Package等等。
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象。
通过.class可以获取一个类的字节码,通过这个字节码可以获取它的构造方法,用.newInstance(Object... initargs) 方法获取这个类的一个实例对象。
两种获取实例对象的方式。
Constructor构造方法类
得到某个类的所有构造方法:
Construcor[] constructors = Class.forName("java.lang.String").getConstructors();
得到某一个构造方法:
Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
//获得方法时要用到类型
创建实例对象:
通常方式:String str = new String(new StringBuffer("abc"));
反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));
//调用获得方法时要用到上面相同类型的实例对象
Class.newInstance()方法:
例子:String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
该方法内部的具体代码是怎样写的呢?用到了缓存机制来保存默认构造方法的实例对象。
反射的性能低下。
Field
综合案例:把对象中所有String类型的属性值中的a都改成b
方法的反射
用反射调用执行一个对象的成员方法
用反射调用一个类的main方法
数组的反射
维数和类型相同数数组使用的是同一个Class对象
基本类型数组的父类不是Object
HashCode
运行结果:
5
1
0
当一个对象被存储进HashSet集合中以后,就不能修改这个对象的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同乐,这种情况下,即使在contains方法使用该对象的当前应用作为参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露。
用反射技术开发框架的原理
编译时阶段:写源代码、用javac编译
运行时阶段:运行程序
二、静态导入
import语句可以导入一个类或者某个包中的所有类
import static语句导入一个类中的某个静态方法或所有静态方法
package day1; import static java.lang.Math.max; public class StaticImport { public static void main(String[] args){ System.out.println(max(3,9)); } }
三、可变参数
特点:
1、只能出现在参数列表的最后。
2、...位于变量类型和变量名之间,前后有无空格都可以。
3、调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。
package day1; public class VarableParameter { public static void main(String[] args) { add(1,8,0,3,5); } public static int add(int ...args){ for(int i : args){ System.out.println(i); } return args.length; } }
四、for循环增强
语法:
for(type 变量名:集合变量名){
}
注意事项:
迭代变量必须在()中定义。
集合变量可以是数组或实现了Iterable接口的集合类
举例:
package day1; import java.util.ArrayList; import java.util.List; public class ForDemo { public static void main(String[] args){ List<String> list = new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); for(String e : list){ System.out.println(e); } } }
五、自动装箱与拆箱
package day1; public class TEst { public static void main(String[] args){ Integer num1 = 34; int num2 = num1 + 1; System.out.println(num2); } }
六、享元模式
flyweight
如果很多很小的对象,它们有相同的东西,那就可以把它们变成一个对象,把它们不同的东西变成外部的属性,作为方法的参数传入
整数:-128~127 使用的是享元模式
图标显示:i.display(int x,int y);
字符显示i{x,y}
七、枚举
为什么要有枚举?
枚举就是要让某个类型的变量的取值只能为若干个固定值中得一个,否则编译器就会报错。枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通的变量方式在开发阶段无法实现这一目标。
用普通类如何实现枚举功能,定义一个Weekday的类来模拟枚举功能。
私有的构造方法
每个元素分别用一个公有的静态成员变量表示。
可以有若干公有方法或抽象方法,例如,要提供nextDay方法必须是抽象的。
package day1; public class EnumTest { public static void main(String[] args){ WeekDay weekDay = WeekDay.FRI; System.out.println(WeekDay.valueOf("FRI")); WeekDay[] weekDays = WeekDay.values(); System.out.println(weekDays.length); } public enum WeekDay{ SUN(1),MON,TUE,WED,THI,FRI,SAT; private WeekDay(){ } private WeekDay(int i){ System.out.println(i); } } }
枚举元素加小括号表示调用它的带参数的构造方法
枚举元素加大括号表示枚举类的子类
package day1; public class EnumTest { public enum TrafficLamp{ RED(30){ public TrafficLamp nextLamp(){ return GREEN; } }, GREEN(45){ public TrafficLamp nextLamp(){ return YELLOW; } }, YELLOW(5){ public TrafficLamp nextLamp(){ return RED; } }; public abstract TrafficLamp nextLamp(); private int time; private TrafficLamp(int time){ this.time = time; } } }
八、反射(不是java5的新特性,从Java1.2开始就有)
一个类被加载器加载到内存中,占用一片内存空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以他们在
内存中的内容是不同的,这一个个的空间可分别用一个个的对象来表示,这些对象显然具有相同的类型,就是Class类型。
String.class, new String("abcd").getClass() 都是String类的字节码 是同一个对象
Class.forName("java.lang.String")加载类,得到这个类的字节码
有9个预定义的Class对象:8个基本类型和void
isPrimitive() 判定指定的对象是否表示一个基本类型。
boolean isArray() 判定此 Class 对象是否表示一个数组类。
反射:
反射就是把Java类中的各种成分映射成相应的Java类。例如,一个Java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等信息也用一个个的Java类来表示,就像汽车是一个类,汽车中得发动机,变速箱等等也是一个个的类。表示Java类的Class类显然要提供一系列的方法,来获得其中变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,他们是Field、Method、Contructor、Package等等。
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象。
通过.class可以获取一个类的字节码,通过这个字节码可以获取它的构造方法,用.newInstance(Object... initargs) 方法获取这个类的一个实例对象。
两种获取实例对象的方式。
public static void main(String[] args) throws Exception { Constructor constructor = String.class.getConstructor(String.class); String str = (String)constructor.newInstance(new String("abcd")); System.out.println(str); }
public static void main(String[] args) throws Exception { String str = String.class.newInstance(); System.out.println(str); }
Constructor构造方法类
得到某个类的所有构造方法:
Construcor[] constructors = Class.forName("java.lang.String").getConstructors();
得到某一个构造方法:
Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
//获得方法时要用到类型
创建实例对象:
通常方式:String str = new String(new StringBuffer("abc"));
反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));
//调用获得方法时要用到上面相同类型的实例对象
Class.newInstance()方法:
例子:String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
该方法内部的具体代码是怎样写的呢?用到了缓存机制来保存默认构造方法的实例对象。
反射的性能低下。
Field
ReflectPoint pt1 = new ReflectPoint(3,5); Field fieldY = pt1.getClass().getDeclaredField("y"); System.out.println(fieldY.get(pt1));
综合案例:把对象中所有String类型的属性值中的a都改成b
package day1;
import java.lang.reflect.Field;
public class ReflectPoint {
public int x;
public int y;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "itcast";
public ReflectPoint(int x, int y) {
this.x = x;
this.y = y;
}
public static void main(String[] args) throws Exception{
ReflectPoint pt1 = new ReflectPoint(3,5); Field fieldY = pt1.getClass().getDeclaredField("y"); System.out.println(fieldY.get(pt1));
changeStringValue(pt1);
}
private static void changeStringValue(Object obj) throws IllegalArgumentException, IllegalAccessException {
Field[] fields = obj.getClass().getFields();
for(Field field : fields){
if(field.getType() == String.class){
String strValue = (String)field.get(obj);
strValue = strValue.replaceAll("b", "a");
field.set(obj, strValue);
System.out.println(field.get(obj));
}
}
}
}
方法的反射
用反射调用执行一个对象的成员方法
Method methodCharAt = String.class.getMethod("charAt", int.class); String str = "abcd"; //调用静态方法是对象传null //methodCharAt.invoke(null,2) System.out.println(methodCharAt.invoke(str,2));
用反射调用一个类的main方法
String className = null; Method mainMethod = Class.forName(className).getMethod("main", String[].class); mainMethod.invoke(null, new Object[]{new String[]{"111","888","fdad"}});
数组的反射
维数和类型相同数数组使用的是同一个Class对象
基本类型数组的父类不是Object
package day1; import java.lang.reflect.Array; public class ReflectArray { public static void main(String[] args) { printObj(new Object[]{"fda","fda","88"}); } private static void printObj(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
package day1; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class ReflectTest2 { public static void main(String[] args) { Collection collections = new HashSet(); ReflectPoint pt1 = new ReflectPoint(3,3); collections.add(pt1); pt1.x = 5; Iterator it = collections.iterator(); while(it.hasNext()){ ReflectPoint pt2 = (ReflectPoint)it.next(); System.out.println(pt2.x); } collections.remove(pt1); ReflectPoint pt5 = new ReflectPoint(3,3); collections.remove(pt5); System.out.println(collections.size()); pt1.x = 3; collections.remove(pt5); System.out.println(collections.size()); } }
运行结果:
5
1
0
当一个对象被存储进HashSet集合中以后,就不能修改这个对象的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同乐,这种情况下,即使在contains方法使用该对象的当前应用作为参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露。
用反射技术开发框架的原理
InputStream ips = new FileInputStream("config.properties"); Properties props = new Properties(); props.load(ips); ips.close(); String className = props.getProperty("className"); Collection collections1 = (Collection)Class.forName(className).newInstance(); System.out.println(collections1.size());
相关文章推荐
- 黑马程序员--Java基础加强--12.利用反射操作泛型I【与反射+泛型相关的接口类型综述】【Type】【ParameterizedType】【个人总结】
- 黑马程序员--Java基础加强--02.代码简化 书写规律I_原始数据类型【重载】【多态】【泛型】【泛型限定】【个人总结】
- 黑马程序员--Java基础加强--04.代码简化 书写规律III_数组参数【重载】【数组】【可变参数数组】【泛型可变参数数组】【个人总结】
- 黑马程序员--Java基础加强--06.【泛型通配符限定】【个人总结】
- Java基础加强总结(二)——泛型
- Java基础加强总结(一)——注解(Annotation)
- 黑马程序员--Java基础加强--07.【反射创建对象 操作字段 调用方法的异同】【个人总结】
- 黑马程序员--Java基础加强--08.【javac兼容编译原则】【可变参数数组编译】【个人总结】
- Java基础加强总结(一)——注解(Annotation)
- java基础加强--要点总结2
- 黑马程序员__关于学习Java基础加强的总结_1
- 黑马程序员--Java基础加强--05.【泛型通配符】【个人总结】
- Java基础加强总结(一)——注解(Annotation)
- 黑马程序员--Java基础加强--11.【MyEclipse使用快捷键提取方法的要点】【个人总结】
- 黑马程序员--Java基础加强--13.利用反射操作泛型II【TypeVariable】【GenericArrayType】【WildcardType】【Type及其子接口的来历】【个人总结】
- Java基础加强总结——代理(Proxy)
- 黑马程序员----【java基础加强】张孝祥视频总结1
- 这是我在四天内听完陈老师讲的java基础加强后的总结
- Java基础加强总结(5)(代理)
- Java基础加强总结之动态代理(Proxy)