枚举&注解&反射
枚举
枚举的三种实现方式
1.定义class类的方式
public class Level {
public static final Level LOW = new Level(0);
public static final Level MEDIUM = new Level(50);
public static final Level HIGH = new Level(100);
private int value;
private Level() {
}
private Level(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
2.定义enum加上属性值的方式
public enum Level2 {
LOW(0), MEDIUM(50), HIGN(100);
private int value;
private Level2(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
3…定义enum不加属性值
public enum Level3 {
LOW, MEDIUM, HIGH;
}
枚举的方法
public class Demo1 {
public static void main(String[] args) {
System.out.println(Level.LOW.getValue());//0
System.out.println(Level2.LOW.getValue());//0
System.out.println(Level3.LOW);//LOW
System.out.println(Level3.LOW.name());//LOW
System.out.println(Level2.LOW.compareTo(Level2.HIGN));//-2
System.out.println(Level2.LOW.ordinal());//0
System.out.println(Level2.LOW.toString());//LOW
System.out.println(Level2.valueOf(Level2.class, "MEDIUM").name());//MEDIUM
}
public void haha(Level2 l){
switch (l){
case LOW:break;
case MEDIUM:break;
default:break;
}
}
}
枚举接口
public enum Level3 implements Lshow {
LOW(){
@Override
public void show() {
System.out.println("low");
}
}, MEDIUM{
@Override
public void show() {
System.out.println("medium");
}
}, HIGH{
@Override
public void show() {
System.out.println("high");
}
};
/*@Override
public void show() {
}*/
}
interface Lshow {
void show();
}
public static void main(String[] args) {
Level3.LOW.show();// low
Level3.HIGH.show();// high
}
注意事项
1.最好不要修改里面的属性值
2.枚举类默认继承的是java.lang.Enum而不是Object类
3.枚举类默认被final修饰,不能有子类
4.只能有private构造方法
5.switch中使用时不能携带类名,直接使用常量名
6.不能定义name属性,因为已经自带了
7.不要提供set方法
注解
内置注解
@Override:重启父类的方法
@Deprecated:废弃方法
@SuppressWarnings(“all”):抑制所有警告
@FunctionalInterface:函数式接口
示例:
//@SuppressWarnings("all")
public class Demo2 {
@Override
public String toString(){
return super.toString();
}
public void test1(){
}
public void test1New() {
}
public static void main(String[] args) {
Person p = new Person();
p.setAge(10);
System.out.println(p.getAge());
p.setAge2(-1);
System.out.println(p.getAge());
}
}
class Person {
private String name;
private Integer age;
public Integer getAge() {
return age;
}
/**
* 此方法已废弃,请用setAge2
* @param age
*/
@Deprecated
public void setAge(Integer age) {
this.age = age;
}
public void setAge2(Integer age) {
if(age > 150 || age < 0) {
throw new RuntimeException("输入年龄范围有误");
}
this.age = age;
}
}
元注解
- @Retention:持久化方式
- SOURCE:注解仅存在编译期间
- CLASS:将注解存储再class文件中
- RUNTIME:存在class里且jvm可读
- @Documented:注解是否包含在用户文档中,javadoc
- @Target:TYPE(类,接口),FILED(字段),METHOD(方法)
- @Inherited:标记这个注解是自动继承的
自定义注解
至少包含一个ElementType,包含RetentionPolicy
@MyAnnotation(value = {"王五","张三"}, num=18)
public class Demo3 {
public void add(){
}
}
// 注解是否包含在文档中
@Documented
// 持久化策略
@Retention(RetentionPolicy.RUNTIME)
// 用途类型
@Target({ElementType.TYPE,ElementType.METHOD})
// 可以继承
@Inherited
@interface MyAnnotation{
String[] value() default "李四";//必须要传值,否则报错
int num() default 12;
}.
反射
类加载器
* 引导类加载器(爷)
* 扩展类加载器(父)
* 应用类加载器(子)
双亲委派模型
* 避免类的重复加载
* 先将请求转交给父加载器,只有父反馈无法完成加载请求时子才会尝试去加载
类加载器和资源目录
public class Demo4 {
public static void main(String[] args) throws IOException {
InputStream resourceAsStream = Demo4.class.getClassLoader().getResourceAsStream("config.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(resourceAsStream));
String res = br.readLine();
System.out.println(res);
br.close();
}
}
注意事项:
- config.txt建在src目录下才能读取
- 如果将config.txt建在source目录下,source目录设置为资源目录,那么将读取source目录下的config.txt
- 如果中文乱码需要在settings中file encoding设置为utf-8
Class与加载方式
* 类加载器将字节码class文件加载到内存,以Class类型存储,例如Class c = Demo.class
public class Demo5 {
public static void main(String[] args) throws ClassNotFoundException {
// 第一种方式,通过类名.class加载类
Class<Person> c1 = Person.class;
System.out.println(c1);
// 第二种方式,通过类的对象获取类的信息
Person p = new Person();
Class<Person> c2 = (Class<Person>) p.getClass();
// 第三种方式,通过通过类的名称加载类
Class<Person> c3 = (Class<Person>) Class.forName("core.eighth.Person");
System.out.println(c1==c2 && c1==c3);// true
}
private static Class getClass(String name) throws ClassNotFoundException {
return Class.forName(name);
}
}
反射中的构造器
public class Demo6 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<Student> clazz = (Class<Student>) Class.forName("core.eighth.Student");
// 根据Class对象获取Student的无参构造器
Constructor<Student> c1 = clazz.getConstructor();
Student s1 = c1.newInstance();
System.out.println(s1);
// 根据Class对象获取Student的有参构造器
Constructor<Student> c2 = clazz.getConstructor(String.class, Integer.class);
Student s2 = c2.newInstance("李四", 19);
System.out.println(s2);
// 根据Class对象获取Student的私有构造器
Constructor<Student> c3 = clazz.getDeclaredConstructor(String.class);
// 需要设置忽略权限限制
c3.setAccessible(true);
Student s3 = c3.newInstance("王五");
System.out.println(s3);
}
}
class Student {
private String name;
private Integer age;
private Student(String name) {
this.name = name;
this.age = 88;
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
反射中的方法
public class Demo7 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// 加载类
Class clazz = Class.forName(“core.eighth.Student”);
// 获取类的构造方法
Constructor c = clazz.getConstructor();
// 创建对象
Object o = c.newInstance();
// 获取类的方法
Method setName = clazz.getMethod(“setName”, String.class);
// 参数一:哪个对象要执行方法
// 参数二:调用方法时传递的参数0-n
setName.invoke(o, “张三”);
// 对于私有方法需要用getDeclaredMethod并开放执行权限
Method setAge = clazz.getDeclaredMethod(“setAge”, Integer.class);
setAge.setAccessible(true);
setAge.invoke(o, 90);
System.out.println(o);
}
}
反射中的属性
public class Demo8 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
Class clazz = Class.forName("core.eighth.Student");
Constructor c = clazz.getConstructor();
Object o = c.newInstance();
// phoneNum为public属性
Field phoneNum = clazz.getField("phoneNum");
phoneNum.set(o,"12312345678");
// name为private属性
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(o,"王二");
System.out.println(o);
}
}
反射与注解
1.创建@TableAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface TableAnnotation {
String value();
}
2.创建@ColumnAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface ColumnAnnotation {
String name();
String type();
String length();
}
3.测试反射及注解功能
public class Demo9 {
public static void main(String[] args) throws ClassNotFoundException {
Class c = Class.forName("core.eighth.Book");
Annotation[] annotations = c.getAnnotations();
for(Annotation a : annotations) {
System.out.println(a);
}
// 此处需要强转,否则不能获取具体方法
TableAnnotation tableAnnotation = (TableAnnotation) c.getAnnotation(TableAnnotation.class);
System.out.println(tableAnnotation.value());
Field[] declaredFields = c.getDeclaredFields();
for(Field f : declaredFields) {
//f.setAccessible(true);
ColumnAnnotation annotation = f.getAnnotation(ColumnAnnotation.class);
System.out.println(f.getName()+":"+annotation.name()+":"+annotation.type()+":"+annotation.length());
}
}
}
@TableAnnotation(value = "book")
class Book{
@ColumnAnnotation(name = "id", type = "int", length = "11")
private int id;
@ColumnAnnotation(name = "name", type = "varchar", length = "50")
private String name;
@ColumnAnnotation(name = "info", type = "varchar", length = "1000")
private String info;
public Book() {
}
public Book(int id, String name, String info) {
this.id = id;
this.name = name;
this.info = info;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", info='" + info + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return id == book.id &&
Objects.equals(name, book.name) &&
Objects.equals(info, book.info);
}
@Override
public int hashCode() {
return Objects.hash(id, name, info);
}
}
内省
1.示意图:
2.程序实现
public class Demo10 {
public static void main(String[] args) throws IntrospectionException {
Class c = Express.class;
BeanInfo beanInfo = Introspector.getBeanInfo(c);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for(PropertyDescriptor p: propertyDescriptors){
Method get = p.getReadMethod();
// 特殊情况:
// 当属性类型是boolean时,获取的get方法是isFlag
Method set = p.getWriteMethod();
System.out.println(get);// 获取某个属性的get方法
System.out.println(set);// 获取某个属性的set方法
System.out.println(p.getName());// 获取某个属性的名称
System.out.println(p.getPropertyType());// 获取某个属性的类型
System.out.println("-----------");
}
}
}
class Express implements Serializable {
private static final long serialVersionUID = -4063690855571507827L;
private String number;
private String name;
private String phone;
private String address;
private boolean flag;
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public Express() {
}
public Express(String number, String name, String phone, String address) {
this.number = number;
this.name = name;
this.phone = phone;
this.address = address;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Express{" +
"number='" + number + '\'' +
", name='" + name + '\'' +
", phone='" + phone + '\'' +
", address='" + address + '\'' +
'}';
}
}
3.输出结果:
public java.lang.String core.Express.getAddress()
public void core.Express.setAddress(java.lang.String)
address
class java.lang.String
-----------
public final native java.lang.Class java.lang.Object.getClass()
null
class
class java.lang.Class
-----------
public boolean core.Express.isFlag()
public void core.Express.setFlag(boolean)
flag
boolean
-----------
public java.lang.String core.Express.getName()
public void core.Express.setName(java.lang.String)
name
class java.lang.String
-----------
public java.lang.String core.Express.getNumber()
public void core.Express.setNumber(java.lang.String)
number
class java.lang.String
-----------
public java.lang.String core.Express.getPhone()
public void core.Express.setPhone(java.lang.String)
phone
class java.lang.String
-----------
4.注意事项
(1)内省机制针对的是bean类型的java类
(2)当属性类型是boolean时,获取的get方法是isFlag