张孝祥java高新技术 --- jkd1.5 新特性 -- 精华总结
时间:2022-07-25
本文章向大家介绍张孝祥java高新技术 --- jkd1.5 新特性 -- 精华总结,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
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. 枚举
- 枚举类的定义 重点:1. 枚举类中每一个元素都是这个类的子类. 下面的操作更能说明这一点. 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;
}
}
- 枚举类中可用的方法 运行结果 MON 0 MON 7
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
- 构造方法必须写在成员的下面.
- 枚举的构造方法必须是private的
- 枚举的每一个成员都是枚举的子类
- 只要调用枚举类, 就会初始化枚举子类, 子类又会调用父类的构造方法.
- 每一个枚举类的子类默认调用的是枚举类的无参构造方法.
- 调用枚举的有参构造方法,可以使用"子类名(参数)"的形式
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);
}
}
- 为枚举添加抽象方法, 下面是一个交通信号灯亮的顺序枚举类 运行结果:
YELLOW
从这个demo可以得出以下结论:
- 枚举中可以定义抽象方法
- 进一步说明, 每一个枚举的成员都是枚举的子类, 子类必须实现父类的抽象方法.
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());
}
}
- 为上一个交通信号灯案例添加时间. 这个时间我们可以放在构造方法中. 运行结果
YELLOW 亮灯时间: 45
结论
- 子类调用父类的构造方法。
- 每一个枚举成员都是父类的一个子类。
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());
- 如何得到字节码对应的实例对象: 有三种方法
- Class.class(); 类名.class();
- new Date().getClass()
- Class.forName("类的全限定名")
- 九个预定义的class实例对象
- 参考Class类的isPrimitive方法.
- 8个基本类型+void
- int , long, short, double, float, char, byte, bollean, 以及void
- Constructor类 我记得 之前说过, 得到Class类以后, 可以调用Class.newInstances() /* * 实例化 */ Class cla4 = Class.forName("java.lang.String"); //我们可以直接使用Class的newInstance()方法. 但注意这个方法是无参的构造方法. Object o4 = cla4.newInstance(); /* * 如果调用一个类的有参构造方法呢? * 使用构造器. 如下操作, 就是调用了含有一个StringBuffer类型参数的构造方法 * 这样调用的就是有参的构造方法 */ Constructor<?> con4 = cla4.getConstructor(StringBuffer.class); Object o44 = con4.newInstance(new StringBuffer("aaa")); System.out.println(o44);
//获得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);
- Field
- 如何获取共有字段 下面的代码在main方法中执行
/** * 字段 * 如何获取共有字段 */ 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;
}
}
- Method
- 如何获取一个类的指定方法呢 通过反射调用getMethod()方法,在执行invoke方法即可。 如果想获取所有的方法, 可以使用getMethods()方法。
- 如果在使用Method.invoke(参数1,参数2): 如果第一个参数是null,则表示这是调用的一个静态方法。
/**
* 方法反射
*/
String str1 = "abc";
//第一步:通过反射调用指定方法
Method method = String.class.getMethod("charAt", int.class);
//第二步: 执行方法
char c = (char) method.invoke(str1, 2);
System.out.println(c);
- webpack学习(五)配置详解
- 1131: [POI2008]Sta
- 3172: [Tjoi2013]单词
- WebApiThrottle限流框架使用手册
- webpack学习(六)打包压缩js和css
- 1051: [HAOI2006]受欢迎的牛
- 1572: [Usaco2009 Open]工作安排Job
- 深海中的STL—mt19937
- 探索ASP.NET MVC5系列之~~~4.模型篇---包含模型常用特性和过度提交防御
- POJ1201 Intervals(差分约束)
- 【NLP】十分钟快览自然语言处理学习总结
- MVC5 网站开发之九 网站设置
- Redis安全小结
- webpack学习(七)打包压缩图片
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 详解Linux iptables 命令
- 详解fedora 开启 apache 并 开启目录浏览模式
- CentOS新建用户并使能密钥登录的方法
- Linux系统扩容根目录磁盘空间的操作方法
- Linux如何查看进程栈信息示例
- linux查看硬盘大小与挂载硬盘的实现
- centos6.5 安装hadoop1.2.1的教程详解【亲测版】
- Linux中没有rc.local文件的完美解决方法
- 详解linux lcd驱动编写
- Linux下安装telnet的方法
- Linux 安装二进制MySQL 及 破解MySQL密码的方法
- Linux创建进程达到65535的方法
- SSH 上传文件及文件夹到linux服务器的方法
- apache tika检测文件是否损坏的方法
- Linux下二进制编译安装MySql centos7的教程