您的位置:首页 > 编程语言 > Java开发

Java基础加强总结(1)

2011-10-01 23:06 316 查看
一、做开发时的两个阶段

编译时阶段:写源代码、用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());
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐