概述
一、反射
1.反射的概念
反射的引入:
Object obj = new Student();
若程序运行时接收到外部传入的一个对象,该对象的编辑类型是Object,但程序又需要调用该对象运行类型的方法:
1.若编译和运行类型都知道,使用instanceof判断后,强转。
2.编译时根本无法预知该对象属于什么类,程序只能依靠运行时信息来发现对象的真实信息,这时就必须使用反射了。
3.要是想得到对象真正的类型,就得使用反射。
什么是反射机制?
简单的来说,反射机制指的是程序在运行时能获取自身的信息。在java中,只要给定类的名字,
那么就可以通过反射机制来获得类的所有信息。
反射机制的优点与缺点:
为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念,
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有意降低类之间的耦合性。
一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE开发。
它的确定是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作
总是慢于只直接执行相同的操作。
Class类和Class类实例:
Java程序中的各个Java类属于同一类事物,描述这类事物的Java类就是Class类。
对比提问:众多的人用一个什么类表示?众多的Java类用一个什么类表示?
人 Person
Java类 Class
对比提问:Person类代表人,它的实例对象就是张三,李四这样的一个个具体的人,Class类代表Java类,
它的各个实例对象又分别对应什么呢?对应各个类在内存中的字节码,例如:Person类的字节码,ArrayList类的字节码,等等;
一个类被类加载器加载到内存中,占有一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以
它们在内存中的内容是不同的;
![](https://file2.kaopuke.com:8081/files_image/20230527/202305270115569257179.jpg)
用类来描述对象,类:描述数据的结构;
用元数据来描述Class,MetaData(元数据):描述数据结构的结构;
反射就是得到元数据的行为;
备注:一个类在虚拟机中只有一份字节码;
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
2.获取class对象的三种方式
public class Student {
}
/*
* 获取Class对象的三种方式:
* 1.Object类中getClass()方法:必须通过对象调用
* 2.任何的数据类型(包括基本数据类型),都有一个静态属性(class属性):
* 3.Class类的静态方法:forName(全名限定的类名):
*
* 常用:第3种
*/
public class Demo {
public static void main(String[] args) throws ClassNotFoundException {
Student stu = new Student();//会在内存中产生一个Class对象
Class c1 = stu.getClass();
Class c2 = Student.class;
Class c3 = Class.forName("包名.Student");
System.out.println("c1 == c2 : " + (c1 == c2));
System.out.println("c1 == c3 : " + (c1 == c3));
}
}
3.九个预定义Class对象
基本的Java类型(boolean,byte,char,short,int,long,float和double)和关键字void通过class属性也表示为Class对象;
Class类中boolean isPrimitive():判定指定的Class对象是否表示一个基本类型。
包装类和Void类的静态TYPE字段:
Integer.TYPE==int.class;
Integer.class==int.class;
数组类型的Class实例对象:
Class<String[]> clz = String[].class;
Class类中boolean isArray():判定此Class对象是否标识一个数组类型。
public class Demo {
public static void main(String[] args){
Class intClass = int.class;
System.out.println("int.class: "+intClass);
System.out.println("intClass.isPrimitive(): "+intClass.isPrimitive());
Class IntegerClass = Integer.class;
System.out.println("IntegerClass.isPrimitive(): "+IntegerClass.isPrimitive());
System.out.println("Integer.class: "+IntegerClass);
Class IntegerTypeClass = Integer.TYPE;
System.out.println("Integer.TYPE: "+IntegerTypeClass);
System.out.println(intClass == IntegerClass);
System.out.println(intClass == IntegerTypeClass);
Class StringArrayClass = String[].class;
System.out.println("StringArrayClass.isArray(): "+StringArrayClass.isArray());
Class intArrayClass = int[].class;
System.out.println("StringArrayClass == intArrayClass:"+(StringArrayClass == intArrayClass));
Class voidClass = void.class;
System.out.println("voidClass:"+voidClass);
Class VoidClass = Void.TYPE;
System.out.println("VoidClass:"+VoidClass);
Class c = Void.class;
System.out.println("Void.class:"+c);
}
//这两个自定义的方法是可以的,一个int,一个Integer
//包装类与基本数据类型的字节码是不一样的
private void show(int a){}
private void show(Integer i){}
}
4.利用Class获取类的属性信息
class A{}
interface B{}
interface C{}
public class Demo extends A implements B,C{
public class D{};
public interface E{};
public static void main(String[] args){
Class DemoClass = Demo.class;
System.out.println("DemoClass:"+DemoClass);
//得到包名
Package package1 = DemoClass.getPackage();
System.out.println("package1:"+package1);
//得到全限定名
String name = DemoClass.getName();
System.out.println("name:"+name);
//得到类的简称
String simpleName = DemoClass.getSimpleName();
System.out.println("simpleName:"+simpleName);
//得到父类
Class superclass = DemoClass.getSuperclass();
System.out.println("superclass:"+superclass);
System.out.println("superclass.getSimpleName():"+superclass.getSimpleName());
//得到接口
Class[] interfaces = DemoClass.getInterfaces();
System.out.println("interfaces:"+interfaces);
for(Class interfaceClass:interfaces){
System.out.println("interfaceClass:"+interfaceClass);
}
//获得public修饰的类
//返回一个包含某些Class对象的数组,
//这些对象表示属于此Class对象所表示的类的成员的所有公共类和接口。
//(如果内部类前面没有加public的话那么得不到!)
Class[] classes = DemoClass.getClasses();
System.out.println("classes:"+classes);
for(Class classesClass:classes){
System.out.println("classesClass:"+classesClass);
}
//获得修饰符
int modifiers = DemoClass.getModifiers();
System.out.println("modifiers:"+modifiers);
System.out.println("Modifier.toString(modifiers):"+Modifier.toString(modifiers));
}
}
5.通过Class对象获取构造方法
public class Student {
/**********构造方法************/
public Student(){
System.out.println("公有无参的构造方法");
}
public Student(float f){
System.out.println("公有float参数的构造方法 : f = " + f);
}
protected Student(int n){
System.out.println("受保护的int参数的构造方法:n = " + n);
}
Student(String s){
System.out.println("(默认)的String参数的构造方法:s = " + s);
}
private Student(char c){
System.out.println("(私有)的char参数的构造方法: c = " + c);
}
public void show(){
System.out.println("我show......");
}
}
/*
* 通过Class对象可以获取类的:
* 1.构造方法:
* 2.成员属性:
* 3.成员方法:
*
* 1.获取构造方法:
* --批量获取构造方法:
* public Constructor[] getConstructors():获取所有"公有"的构造方法(包含父类"公有"的构造方法)
* public Constructor[] getDeclaredConstructors():获取所有的构造方法,包括私有、受保护、默认、公有(不包含继承的方法)
* --获取单个的构造方法,并调用:
* public Constructor getConstructor(Class ... parameterTypes):获取某个"公有"的构造方法
* public Constructor getDeclaredConstructor(Class ... parameterTypes):获取某个构造方法,包括私有、受保护、默认、公有
* 调用某个构造方法:
* Constructor的newInstance()
*/
public class Demo {
public static void main(String[] args) throws Exception {
//1.加载Class对象
Class stuClass = Class.forName("cn.itcast.demo02_通过Class对象获取构造方法.Student");
//2.获取它内部所有的公有构造方法;
Constructor[] conArray = stuClass.getConstructors();
for(Constructor c : conArray){
System.out.println(c);
}
System.out.println("--------所有的构造方法,包括私有、受保护、默认-----------");
conArray = stuClass.getDeclaredConstructors();
for(Constructor c : conArray){
System.out.println(c);
}
System.out.println("---------获取公有、无参的构造方法,并调用---------------");
Constructor con = stuClass.getConstructor();
//调用此构造方法
Object obj = con.newInstance();//会产生Student对象空间
Student stu = (Student)obj;
stu.show();
System.out.println("---------获取公有、带参的构造方法,并调用---------------");
con = stuClass.getConstructor(float.class);//指定调用公有的float参数的构造方法;
obj = con.newInstance(3.5F);//传递实参
System.out.println("-----------获取私有、带参的构造方法,并调用--------------");
con = stuClass.getDeclaredConstructor(char.class);
con.setAccessible(true);//暴力访问(会忽略访问修饰符)
con.newInstance('男');
System.out.println(con);
}
}
P.S.:对于枚举而言,反射依然没有办法重新创建对象,对于枚举,安全!
enum Cat{
CAT1,CAT2,CAT3;
private Cat(){}
}
public class Demo03 {
public static void main(String[] args) throws Exception{
Class CatClass = Cat.class;
//错误在这一行发生,就是说对枚举而言这种方法连构造器都获得不了,编译可以通过,但是运行就通不过了
Constructor constructor = CatClass.getDeclaredConstructor();
constructor.setAccessible(true);
Object newInstance = constructor.newInstance();
System.out.println(newInstance);
System.out.println(CatClass);
System.out.println(CatClass.isEnum());//true,是枚举
}
}
6.通过Class对象获取成员属性
public class Student {
//**************成员属性**************//
private String name;
int age;
protected char sex;
public String phoneNum;
public String getName(){
return this.name;
}
}
/*
* 通过Class对象获取成员属性:
* 1.获取成员属性:
* --批量获取成员属性:
* public Field[] getFields():获取所有"公有"的成员属性
* public Field[] getDeclaredFields():获取所有的成员属性,包括私有、受保护、默认、公有
* --获取单个的成员属性,并调用:
* public Field getField(Class ... parameterTypes):获取某个"公有"的成员属性
* public Field getDeclaredField(Class ... parameterTypes):获取某个成员属性,包括私有、受保护、默认、公有
* 为成员属性赋值:
* Field类的set(Object target,Object value)
*/
public class Demo {
public static void main(String[] args) throws Exception{
Class stuClass = Class.forName("cn.itcast.demo03_通过Class对象获取成员属性.Student");
System.out.println("------------获取所有公有的成员属性--------------");
Field[] fieldArray = stuClass.getFields();
for(Field f : fieldArray){
System.out.println(f);
}
System.out.println("-----------获取所有的成员属性,包括私有--------------");
fieldArray = stuClass.getDeclaredFields();
for(Field f : fieldArray){
System.out.println(f);
}
System.out.println("-----------获取公有成员,并赋值--------------");
Field f = stuClass.getField("phoneNum");
//要赋值,一定要先实例化一个此类的对象
Object obj = stuClass.getConstructor().newInstance();//获取无参的构造方法,并调用
f.set(obj, "18518151155");
System.out.println("----------获取私有成员,并赋值----------------");
f = stuClass.getDeclaredField("name");
f.setAccessible(true);//设置暴力访问
f.set(obj, "张三");
//验证
Student stu = (Student)obj;
System.out.println("验证电话:" + stu.phoneNum);
System.out.println("姓名:" + stu.getName());
}
}
7.通过Class对象获取成员方法
public class Student {
private void show(){
System.out.println("调用的是私有、无参的show()");
}
void show(int n){
System.out.println("默认带参的show(int n) n = " + n);
}
protected void show(String s){
System.out.println("受保护带参的show(String s) s = " + s);
}
public void show(char c){
System.out.println("公有带参的show(char c) c = " + c);
}
}
/*
* 通过Class对象获取成员方法:
* 1.获取成员方法:
* --批量获取成员方法:
* public Method[] getMethods():获取所有"公有"的成员方法
* public Method[] getDeclaredMethods():获取所有的成员方法,包括私有、受保护、默认、公有
* --获取单个的成员方法,并调用:
* public Method getMethod(Class ... parameterTypes):获取某个"公有"的成员方法
* public Method getDeclaredMethod(Class ... parameterTypes):获取某个成员方法,包括私有、受保护、默认、公有
* 调用成员方法:
* Method-->invoke(Object target,Object... args);
*/
public class Demo {
public static void main(String[] args) throws Exception{
Class stuClass = Class.forName("cn.itcast.demo04_通过Class对象获取成员方法.Student");
System.out.println("-------------所有公有的成员方法--------------");
Method[] methodArray = stuClass.getMethods();//包含父类的公有成员方法
for(Method m : methodArray){
System.out.println(m);
}
System.out.println("-------------所有的成员方法,包括私有的-----------");
methodArray = stuClass.getDeclaredMethods();//不包含父类的;
for(Method m : methodArray){
System.out.println(m);
}
System.out.println("--------------获取某个公有的成员方法,并调用-----------");
Method m = stuClass.getMethod("show", char.class);
//先实例化一个Student对象
Object obj = stuClass.getConstructor().newInstance();
m.invoke(obj, '男');
System.out.println("--------------获取某个私有的成员方法,并调用-----------");
m = stuClass.getDeclaredMethod("show");
m.setAccessible(true);//设置暴力访问
m.invoke(obj);
}
}
P.S.:
如果底层方法是静态的,那么可以忽略指定的obj参数,该参数可以为null.
eg:
method.invoke(null);
8.用反射调用可变参数方法
要把可变参数都当做是其对应的数组类型参数;
如show(XX...is)作为show(XX[] is)调用;
若可变参数元素类型是引用类型
JDK内部接收到参数之后,会自动拆包取出参数再分配给该底层方法,为此我们需要把这个数组
实参先包装成一个Object对象或把实际参数作为一个Object一维数组的元素再传递。
若可变参数元素类型是基本类型
JDK内部接收到参数之后,不会拆包,所以可以不必再封装。不过封装了也不会错,所以建议,
不管基本类型还是引用类型都使用Object[]封装一层,保证无误。
class TestMethod{
public static void method1(int ...params){
System.out.println("基本类型的参数:"+params);
}
public static void method2(String ...params){
System.out.println("引用类型的参数:"+params);
}
}
public class Demo01 {
public static void main(String[] args) throws Exception{
System.out.println("666666");
Class testMethodClass = TestMethod.class;
Method method = testMethodClass.getMethod("method1", int[].class);
method.invoke(null,new int[]{1,2,3,4,5});
Method method2 = testMethodClass.getMethod("method2", String[].class);
//推荐写法
method2.invoke(null, new Object[]{new String[]{"1","2","3"}});
//强转为Object类型
method2.invoke(null, (Object)new String[]{"1","2","3","4","5"});
}
}
9.通过反射运行配置文件内容
/*
* 通过反射运行配置文件内容
*/
public class Demo {
public static void main(String[] args)throws Exception {
//利用反射
Class stuClass = Class.forName(getValue("className"));
Method m = stuClass.getMethod(getValue("methodName"));
Object obj = stuClass.getConstructor().newInstance();
m.invoke(obj);
}
public static String getValue(String key) throws IOException{
Properties pro = new Properties();
FileReader in = new FileReader("my.properties");
pro.load(in);
in.close();
return pro.getProperty(key);
}
}
10.通过反射越过泛型检查
/*
* 定义一个具有Integer泛型的集合ArrayList,并尝试向集合中添加一个字符串"abc"
*/
public class Demo {
public static void main(String[] args) throws Exception {
List<Integer> list = new ArrayList<>();
list.add(10);
// list.add("abc");
//获取Class对象
Class listClass = list.getClass();
//获取add()方法
Method addMethod = listClass.getMethod("add", Object.class);
addMethod.invoke(list, "abc");
for(Object obj : list){
System.out.println(obj);
}
}
}
11.反射来获取泛型信息
通过制定对应的Class对象,程序可以获得该类里面所有的Field,不管该Field使用private方法public。
获得Field对象后都可以使用getType()来获取其类型。
Class<?> type = f.getType();//获得字段的类型;
但此方法只对普通Field有效,若该Field有泛型修饰,则不能准确得到该Field的泛型参数,如Map<String,Integer>;
为了获得指定Field的泛型类型,我们采用:
Type gType = f.getGenericType();得到泛型类型
然后将Type类型强转为ParameterizedType,其表示增加泛型后的类型。
Type getRawType()//返回被泛型限制的类型;
Type[] getActualTypeArguments()//返回泛型参数类型
public class Demo {
public Map<String,Integer> map = new HashMap<String,Integer>();
public static void main(String[] args) throws Exception{
Class DemoClass = Demo.class;
Field field = DemoClass.getField("map");
System.out.println(field.getName());
System.out.println(field.getType());
Type genericType = field.getGenericType();
System.out.println(genericType);
//Type这个类里面没有任何的方法,所以需要调用子类的方法,那么大的类型转小的类型,需要强转!
ParameterizedType pt = (ParameterizedType)genericType;
System.out.println(pt);
System.out.println("----------");
//返回表示此类型实际类型参数的Type对象的数组
Type[] actualTypeArguments = pt.getActualTypeArguments();
for(Type type:actualTypeArguments){
System.out.println(type);
}
System.out.println("-----------");
//返回Type对象,表示此类型是其成员之一的类型
Type ownerType = pt.getOwnerType();
System.out.println(ownerType);
System.out.println("----------");
//返回Type对象,表示声明此类型的类或接口
Type rawType = pt.getRawType();
System.out.println(rawType);
String typeName = pt.getTypeName();
System.out.println(typeName);
}
}
动态获取类中信息,就是java反射。可以理解为对类的解剖。
如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用,这时就使用到了反射技术。
P.S.
所谓的框架就是对外提供一些接口,也就是功能扩展的标准,由实现类按照这个接口标准去实现。
框架内部如果需要操纵这些实现类的对象完成某些操作,就可以获取这个实现类的字节码文件,
然后利用反射技术创建这个实现类的对象并且调用相应的方法完成一些操作。
用于描述字节码的类就是Class类,创建对象,可以提取字节码文件中的内容,如字段、构造函数、一般函数。
该类就可以获取字节码文件中的所有内容,那么反射就是依靠该类完成的。想要对一个类文件进行解剖,
只要获取到该类的字节码文件对象即可。
二、设计模式
代理模式
/*
* 这个类要访问数据库的Student信息;
*/
public class StudentService {
public void save(){
//做权限检查
System.out.println("添加一条学员信息");
//做日志记录
}
public void update(){
//做权限检查
System.out.println("修改一条学员信息");
//做日志记录
}
}
public class StudentServiceProxy {
private StudentService stu = new StudentService();
// 做权限检查
public void save() {
check();
stu.save();
log();
}
// 做日志记录
public void update() {
check();
stu.update();
log();
}
private void check() {
System.out.println("做权限检查......");
}
private void log() {
System.out.println("做日志记录......");
}
}
/*
* 当我们需要调用某个方法时,需要在调用前,和调用做一些其他的事情,这时,我们可以
* 为这个定义一个"代理类",在代理类中,重新定义"被代理类"中的方法,并添加新的内容;
*/
public class Demo {
public static void main(String[] args) {
StudentServiceProxy stu = new StudentServiceProxy();
stu.save();
stu.update();
}
}
动态代理
public interface IService {
public void save();
public void update();
}
public class TeacherService implements IService {
@Override
public void save() {
System.out.println("保存一条Teacher信息!");
}
@Override
public void update() {
System.out.println("修改一条Teacher信息!");
}
}
public class StudentService implements IService {
@Override
public void save() {
System.out.println("保存一个Student对象信息");
}
@Override
public void update() {
System.out.println("修改一条Student信息!");
}
}
public class MyHandler implements InvocationHandler {
//1.要代理的对象
private Object target;
//2.通过构造方法赋值
public MyHandler(Object trg){
this.target = trg;
}
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
//将要做的事情,在这里进行插入
check();
Object result = method.invoke(target, args);
log();
return result;
}
private void check() {
System.out.println("做权限检查......");
}
private void log() {
System.out.println("做日志记录......");
}
}
/*
* Java中的动态代理:
*
* 1.一般的代理模式,需要为原类增加"代理类",这样的话,代理类会越来越多;
* 2.Java中的动态代理机制:
* 1).自定义类,实现一个InvocationHandler接口;
* 重写:invoke()方法;
* 2).获取代理对象:
* Proxy类的静态方法:newProxyInstance():
* 注意:Java中的动态代理是基于:接口的(要代理的类,必须是某个接口类型的子类)
*/
public class Demo {
public static void main(String[] args) {
IService service = (IService)Proxy.newProxyInstance(StudentService.class.getClassLoader(),StudentService.class.getInterfaces(),new MyHandler(new StudentService()));
service.save();
service.update();
IService teaService = (IService)Proxy.newProxyInstance(TeacherService.class.getClassLoader(),TeacherService.class.getInterfaces(),new MyHandler(new TeacherService()));
teaService.save();
teaService.update();
}
}
模板设计模式
abstract class Person{
//模板方法。此方法是由子类继承的;
public void show(){
System.out.println("大家好,我是一名 " + getType());
}
//需要子类实现的方法
public abstract String getType();
}
class Student extends Person{
public String getType(){
return "学生";
}
}
class Teacher extends Person{
public String getType(){
return "教师";
}
}
public class Demo {
public static void main(String[] args) {
Student stu = new Student();
stu.show();
Teacher tea = new Teacher();
tea.show();
}
}
装饰模式
public interface IThinkPad {
public void sellComputer();
}
public class ThinkPadE450 implements IThinkPad {
@Override
public void sellComputer() {
System.out.println("卖一台E450!");
}
}
public class ThinkPadX240 implements IThinkPad {
@Override
public void sellComputer() {
System.out.println("卖一台X240");
}
}
public abstract class AbstractThinkPadDealer implements IThinkPad{
private IThinkPad think;
public AbstractThinkPadDealer(IThinkPad think){
this.think = think;
}
@Override
public void sellComputer() {
this.think.sellComputer();
}
}
public class ThinkPad_XSQ_Dealer extends AbstractThinkPadDealer {
public ThinkPad_XSQ_Dealer(IThinkPad think) {
super(think);
}
@Override
public void sellComputer() {
super.sellComputer();
System.out.println("西三旗经销商,送一套三居室!");
}
}
public class ThinkPad_ZGC_Dealer extends AbstractThinkPadDealer {
public ThinkPad_ZGC_Dealer(IThinkPad think) {
super(think);
}
@Override
public void sellComputer() {
super.sellComputer();
System.out.println("中关村经销商,送一辆奔驰!");
}
}
public class Demo {
public static void main(String[] args) {
ThinkPadX240 x240 = new ThinkPadX240();
x240.sellComputer();
System.out.println("选择到中关村经销商那里买:");
IThinkPad think = new ThinkPad_ZGC_Dealer(new ThinkPadX240());
think.sellComputer();
System.out.println("选择到西三旗经销商那里买:");
IThinkPad think2 = new ThinkPad_XSQ_Dealer(new ThinkPadE450());
think2.sellComputer();
System.out.println("选择到中关村经销商那里买,然后中关村经销商又到西三旗经销商那里买:");
IThinkPad think3 = new ThinkPad_ZGC_Dealer(new ThinkPad_XSQ_Dealer(new ThinkPadE450()));
think3.sellComputer();
}
}
三、JDK5和JDK7新特性
public class Demo {
public static void main(String[] args) {
//1.自动装箱和拆箱
Integer intObj1 = 10;//自动装箱
intObj1 = intObj1 + 20;//先拆箱,再装箱;
//2.泛型
List<String> strList = new ArrayList<>();
strList.add("aaa");
// strList.add(10);//编译错误;
//3.增强for循环:可以遍历集合(底层使用迭代器);也可以遍历数组;
for(String s : strList){
System.out.println(s);
}
//4.静态导入
System.out.println("-5的绝对值:" + abs(-5));
//5.可变参数
fun();//可以不传;
fun(432,4324,35,24,32,5,74,6547,6432,523,534,63);
//6.枚举:
}
public static void fun(int...num){
for(int i : num){
System.out.println(i);
}
}
}
自己实现枚举类
public class MyColor {
public static MyColor RED = new MyColor();
public static MyColor GREEN = new MyColor();
public static MyColor BLUE = new MyColor();
private MyColor(){
}
}
public class MyColor2 {
public static MyColor2 RED = new MyColor2("红");
public static MyColor2 GREEN = new MyColor2("绿");
public static MyColor2 BLUE = new MyColor2("蓝");
private String name;
private MyColor2(String n){
this.name = n;
}
@Override
public String toString() {
return "MyColor2 [name = " + this.name + "]";
}
}
public abstract class MyColor3 {
public static MyColor3 RED = new MyColor3("红"){
public void show(){
System.out.println("大家好,我是红色的!");
}
};
public static MyColor3 GREEN = new MyColor3("绿"){
public void show(){
System.out.println("大家好,我是绿色的!");
}
};
public static MyColor3 BLUE = new MyColor3("蓝"){
public void show(){
System.out.println("大家好,我是蓝色的!");
}
};
private String name;
private MyColor3(String n){
this.name = n;
}
@Override
public String toString() {
return "MyColor3 [name = " + this.name + "]";
}
public abstract void show();
}
/*
* 什么是枚举:
* 1.之前我们了解过"单例模式":某个类的对象,在程序运行期间,只有一个实例;
* 2."多例模式":某个类的对象,在程序运行期间,只需要固定数量的实例:
* 例如: 扑克:如果每张扑克是一个类,在程序运行期间,只能有54个实例;
* 骰子:如果每个筛子是一个类,在程序运行期间,只能有2个实例;
* 3.自定一个多例模式:
* 例如:我们程序需要一个"颜色"类(MyColor),但我们的程序在运行期间,只需要三个颜色:红、绿、蓝
* 这时我们可以将MyColor类,设计为:多例模式:
* 1).外部不能随意实例化此类的对象:将构造方法私有;
* 2).内部提供三个此类对象的引用;
*/
public class Demo {
public static void main(String[] args) {
MyColor redColor = MyColor.RED;
MyColor2 greenColor = MyColor2.GREEN;
System.out.println(greenColor);
MyColor3 blueColor = MyColor3.BLUE;
System.out.println(blueColor);
blueColor.show();
}
}
通过enum实现枚举类
public enum MyColor {
RED,GREEN,BLUE;
}
public enum MyColor2 {
RED("红"),GREEN("绿"),BLUE("蓝");
private String name;
private MyColor2(String s){
this.name = s;
}
}
public enum MyColor3 {
RED("红"){
public void show(){
System.out.println("我是红色的!");
}
},GREEN("绿"){
public void show(){
System.out.println("我是绿色的!");
}
},BLUE("蓝"){
public void show(){
System.out.println("我是蓝色的!");
}
};
private String name;
private MyColor3(String s){
this.name = s;
}
public abstract void show();
}
public class Demo {
public static void main(String[] args) {
MyColor redColor = MyColor.RED;
System.out.println(redColor);
MyColor2 greenColor = MyColor2.GREEN;
System.out.println(greenColor);
MyColor3 blueColor = MyColor3.BLUE;
System.out.println(blueColor);
blueColor.show();
}
}
枚举的常用方法
public enum MyColor {
RED,GREEN,BLUE;
}
/*
* 枚举的常用方法:
* int compareTo(E o):比较的是内部的索引值;
* String name():同枚举项的名称;
* int ordinal():获取索引值;
* String toString():打印是:枚举项的名称;
* <T> T valueOf(Class<T> type,String name):获取某个枚举项;
* values() :在帮助文档中没有;作用:将枚举,转换为数组
*/
public class Demo {
public static void main(String[] args) {
MyColor red = MyColor.RED;
MyColor green = MyColor.GREEN;
MyColor blue = MyColor.BLUE;
System.out.println(red.compareTo(green));//-1
System.out.println(red.compareTo(blue));//-2
System.out.println(green.compareTo(red));//1
System.out.println(blue.compareTo(red));//2
System.out.println("red.name() : " + red.name());
System.out.println("red.ordinal() : " + red.ordinal());
System.out.println("green.ordinal() : " + green.ordinal());
System.out.println("blue.ordinal() : " + blue.ordinal());
System.out.println("red.toString() : " + red);
MyColor green2 = MyColor.valueOf(MyColor.class, "GREEN");
System.out.println(green2);
System.out.println("------------------------------------------");
MyColor[] colorArray = MyColor.values();
for(MyColor m : colorArray){
System.out.println(m);
}
}
}
JDK7的新特性
/*
* JDK7的新特性:
* 1.二进制字面量
* 2.数字字面量可以出现下划线
* 3.switch 语句可以用字符串
* 4.泛型简化
* 5.异常的多个catch合并
* 6.try-with-resources 语句
*/
public class Demo {
public static void main(String[] args) {
//1.二进制字面量
System.out.println(10);//十进制
System.out.println(0b1010);//二进制(从JDK7开始)
System.out.println(012);//八进制
System.out.println(0xA);//十六进制
//2.数字字面量可以出现下划线
System.out.println(1_2_3_4_5_6.22);
//3.switch 语句可以用字符串
String s = "+";
switch(s){
case "+":
System.out.println("加法");
break;
case "-":
System.out.println("减法");
break;
}
//4.泛型简化
List<String> strList = new ArrayList<String>();//JDk7以前
List<String> strList2 = new ArrayList<>();//JDK7支持
List<String> strList3 = new ArrayList();//JDK7支持
//5.异常的多个catch合并
try{
//....
}catch(NullPointerException | ArrayIndexOutOfBoundsException | ArithmeticException e){
}catch(Exception e){
}
//6.try-with-resources 语句
try(
FileInputStream in = new FileInputStream("aa.txt");
FileOutputStream out = new FileOutputStream("bb.txt");
) {
//正常读取
//in流不需要关闭,JVM会自动将其关闭;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
最后
以上就是大胆酒窝为你收集整理的Java_反射、几个设计模式、JDK5和JDK7新特性的全部内容,希望文章能够帮你解决Java_反射、几个设计模式、JDK5和JDK7新特性所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复