1. 抽象方法的使用
如果一个方法中大量出现if语句, 那么, 就应该考虑使用抽象来处理. 如下例:
package com.lxl;
public class Weekend {
//周日
public static Weekend SUN = new Weekend();
//周一
public static Weekend MON = new Weekend();
//周二
public static Weekend TUE = new Weekend();
//周三
public static Weekend WES = new Weekend();
//周四
public static Weekend TUR = new Weekend();
//周五
public static Weekend FRI = new Weekend();
//周六
public static Weekend SAR = new Weekend();
/*
* 有一个if语句用来判断, 当前日期的下一个日期是星期几.
*/
public Weekend nextDay(Weekend day){
if(day == SUN) {
return MON;
}else if(day == MON){
return TUE;
}else if(day == TUE){
return WES;
}else if(day == WES){
return TUR;
}else if(day == TUR){
return FRI;
}else if(day == FRI){
return SAR;
}else if(day == SAR){
return SUN;
}else{
return null;
}
}
public static void main(String[] args) {
Weekend sun = Weekend.SUN;
sun.nextDay(sun);
}
}
在这个方法中, 我定义了一周七天. 如果我想知道明天是星期几, 那么我需要写一个if语句, 大量的 if语句来判断, 明天是星期几. 当程序中出现大量的if语句的时候, 就要想到这样的程序不完美, 需要优化. 比如, 我现在有星期八了, 那么你出来需要添加星期八, 还需要修改if语句.
使用抽象来代替if语句.是一个好办法.
修改后的方法如下: 定义了一个抽象方法nextDay
package com.lxl;
public abstract class Weekend {
//周日
public static Weekend SUN = new Weekend(){
@Override
public Weekend nextDay(Weekend day) {
return MON;
}
};
//周一
public static Weekend MON = new Weekend(){
@Override
public Weekend nextDay(Weekend day) {
return TUE;
}
};
//周二
public static Weekend TUE = new Weekend(){
@Override
public Weekend nextDay(Weekend day) {
return WES;
}
};
//周三
public static Weekend WES = new Weekend(){
@Override
public Weekend nextDay(Weekend day) {
return TUR;
}
};
//周四
public static Weekend TUR = new Weekend(){
@Override
public Weekend nextDay(Weekend day) {
return FRI;
}
};
//周五
public static Weekend FRI = new Weekend(){
@Override
public Weekend nextDay(Weekend day) {
return SAR;
}
};
//周六
public static Weekend SAR = new Weekend(){
@Override
public Weekend nextDay(Weekend day) {
return SUN;
}
};
/*
* 当有大量的if语句时, 要考虑如何优化
*/
/*public Weekend nextDay(Weekend day){
if(day == SUN) {
return MON;
}else if(day == MON){
return TUE;
}else if(day == TUE){
return WES;
}else if(day == WES){
return TUR;
}else if(day == TUR){
return FRI;
}else if(day == FRI){
return SAR;
}else if(day == SAR){
return SUN;
}else{
return null;
}
}*/
//定义一个抽象方法
public abstract Weekend nextDay(Weekend day);
public static void main(String[] args) {
Weekend sun = Weekend.SUN;
sun.nextDay(sun);
}
}
采用抽象方法定义nextDay, 就是可以将if..else转换为独立的类.
这样做的好处是, 一旦有了星期八, 那么只需要定义星期八这个常量就好了, 不用修改其他地方.
2. 枚举
package com.lxl;
public class Weekend2 {
//这时一个枚举内部类
public enum Weekend {
//枚举中每一项,实际上都是这个类的一个子类
MON, TUE, WEN, THI, FRI, SAT, SUN
}
public static void main(String[] args) {
//1. 选择的时候, 只能在枚举范围内进行选择
Weekend day = Weekend.MON;
}
}
package com.lxl;
public class Weekend2 {
//这时一个枚举内部类
public enum Weekend {
//枚举中每一项,实际上都是这个类的一个子类
MON, TUE, WEN, THI, FRI, SAT, SUN
}
public static void main(String[] args) {
//1. 选择的时候, 只能在枚举范围内进行选择
Weekend day = Weekend.MON;
//2. 可用的方法
// 打印名字
System.out.println(day.name());
// 序号
System.out.println(day.ordinal());
// 将某个字符串转换为枚举类型
System.out.println(day.valueOf("MON"));
//获取枚举列表
System.out.println(Weekend.values().length);
}
}
first
second
first
first
first
first
first
MON
0
MON
7
package com.lxl;
public class Weekend2 {
//这时一个枚举内部类
public enum Weekend {
//枚举中每一项,实际上都是这个类的一个子类
MON(), TUE(1), WEN, THI, FRI, SAT, SUN;
//3. 为枚举添加构造方法
private Weekend(){System.out.println("first");}
private Weekend(int i){System.out.println("second");}
}
public static void main(String[] args) {
//1. 选择的时候, 只能在枚举范围内进行选择
Weekend day = Weekend.MON;
//2. 可用的方法
// 打印名字
System.out.println(day.name());
// 序号
System.out.println(day.ordinal());
// 将某个字符串转换为枚举类型
System.out.println(day.valueOf("MON"));
//获取枚举列表
System.out.println(Weekend.values().length);
}
}
package com.lxl;
public class EnumTest3 {
//交通信号灯
public enum TrafficLamp{
RED {
@Override
public TrafficLamp nextLamp() {
return YELLOW;
}
},
YELLOW {
@Override
public TrafficLamp nextLamp() {
return BLUE;
}
},
BLUE {
@Override
public TrafficLamp nextLamp() {
return RED;
}
};
//下一个亮的信号灯--抽象方法
public abstract TrafficLamp nextLamp();
}
public static void main(String[] args) {
TrafficLamp red = TrafficLamp.RED;
System.out.println(red.nextLamp());
}
}
package com.lxl;
public class EnumTest3 {
//交通信号灯
public enum TrafficLamp{
RED(30) {
@Override
public TrafficLamp nextLamp() {
return YELLOW;
}
},
YELLOW(45) {
@Override
public TrafficLamp nextLamp() {
return BLUE;
}
},
BLUE(5) {
@Override
public TrafficLamp nextLamp() {
return RED;
}
};
//下一个亮的信号灯--抽象方法
public abstract TrafficLamp nextLamp();
public int time;
private TrafficLamp(int time){
this.time = time;
}
3. 反射
String str = "abc";
Class cla1 = str.getClass();
Class cla2 = String.class;
Class cla3 = Class.forName("java.lang.String");
/*
* 同一份字节码, 在内存中只有一份
*/
System.out.println(cla1 == cla2 );
System.out.println(cla2 == cla3);
/*
* 判断,一个类型是否是基本类型. 基本类型有9个: 8个基本类型+void.
* int long short float double char byte boolean
*/
//String 不是基本类型
System.out.println(str.getClass().isPrimitive());
//int 是基本类型
System.out.println(int.class.isPrimitive());
//Integer 不是基本类型
System.out.println(Integer.class.isPrimitive());
//int 和 Integer 是不同的类型, 他们在内存中的字节码是不同的
System.out.println(int.class == Integer.class);
//Integer.Type方法返回的是基本类型int的字节码
System.out.println(Integer.TYPE == int.class);
//数组也是一个Class对象
//int[]数组不是基本类型
System.out.println(int[].class.isPrimitive());
//int[] 数组是数组么? 是的
System.out.println(int[].class.isArray());
//获得String这个类的所有个构造方法
Constructor<?>[] cons = String.class.getConstructors();
//获得String的指定构造方法: String(StringBuffer s){}
//下面表示只接受一个参数StringBuffer类型的构造方法
Constructor<?> con = String.class.getConstructor(StringBuffer.class);
//将构造方法实例化
Object o = con.newInstance(new StringBuffer("abc"));
System.out.println(o);
/**
* 字段
* 如何获取共有字段
*/
RefelectPoint rp = new RefelectPoint(4,6);
//现在我要通过反射获取rp对象中的x字段的值和y字段的值
Field fieldy = rp.getClass().getField("y");
/*
* 注意: 这里的fieldx表示的是字段, 他不代表任何值. 因为RefelectPoint有很多歌对象,
* fieldx仅表示这些对象中的指定字段. 那到底是哪个对象的值呢? 也就是如何获取这个值呢?
*
* 注意, 使用这种方法只能获得public域的参数
*/
System.out.println(fieldy.get(rp));
/*
* 那如何获取private类型的参数呢
* 如果直接获取会报告异常: java.lang.NoSuchFieldException: x
*
* 我们可以通过对象的getDeclareField("x")来获取.
* 这个时候, 我们调用这个方法, 返回的依然是一个异常 :modifiers "private"
* 这时我们要调用setAccessible(true)强制通知,告诉编译器我可以获取这个私有属性
*/
Field fieldx = rp.getClass().getDeclaredField("x");
fieldx.setAccessible(true);
System.out.println(fieldx.get(rp));
/**
* 将一个对象中的所有String类型的成员变量的值中的b改成a
* 思路:
* 1. 获取所有的String类型的成员
* 2. 获取成员对应的值
* 3. 通过正则表达式或者replaceAll方法对字符串进行替换
*/
Class cla5 = RefelectPoint.class;
Constructor<?> cons5 = cla5.getConstructor(int.class, int.class);
Object o5 = cons5.newInstance(5, 10);
Field[] f5s = cla5.getFields();
for(Field f5: f5s){
//获取Field的类型
Class<?> t5 = f5.getType();
//判断是否是String类型,只需看他的字节码是否是同一份就可以了.
if(t5 == String.class){
String v5 = (String) f5.get(o5);
v5 = v5.replaceAll("b", "a");
f5.set(o5, v5);
System.out.println(v5);
}
}
public class RefelectPoint {
private int x;
public int y;
public RefelectPoint(int x, int y){
this.x = x;
this.y =y;
}
}
/**
* 方法反射
*/
String str1 = "abc";
//第一步:通过反射调用指定方法
Method method = String.class.getMethod("charAt", int.class);
//第二步: 执行方法
char c = (char) method.invoke(str1, 2);
System.out.println(c);