天天看点

Java接口、注解、反射(Java基础系列内容)

写在前面

  你们好,我是小庄。很高兴能和你们一起学习Java。如果您对Java感兴趣的话可关注我的动态.

  

写博文是一种习惯,在这过程中能够梳理和巩固知识。

一、接口

什么是接口?

    接口(英文:

interface

);接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。

接口的

特点

    1、接口无法被实例化,但可以被实现,通过

implements

关键字

    2、一个类可以实现多个接口,如:class Test implements a,b{}

    3、实现接口的类必须实现接口的所有未实现方法,否则只能将类设置为抽象类

    4、类只能继承一个类,但是可以实现多个接口,继承和实现可以同时存在,当实现多个接口时,必须先继承类再实现多个接口

//接口的定义,关键字interface
public interface Action{
	//接口的方法,自定义未实现
	public void eat();
}
//定义第二个接口
interface Feature{}
//定义一个被继承的父类
public class Animal{}
//定义一个类实现这个接口
public class Cat implements Action{
	//必须实现接口定义的未实现方法,否则编辑器报错
	public void eat(){
		//这里些实现的内容
		System.out.println("我正在吃美味的鱼");
	}
}
//未实现接口的方法只能被设置为抽象类
public abstract Dog implements Action{}

//继承类的同时实现多个接口
public class Flsh extends Animal implements Feature,Action{
	public void eat(){
		//这里些实现的内容
		System.out.println("我正在吃水蚤");
	}
}
           

二、注解

什么是注解?

    可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。

注解分为内置注解和元注解

1、内置注解
内置注解 作用

@Override

标明一个方法打算重写超类(java.lang.*)中的另一个方法,子类重写父类的方法

@Deprecated

可用于修饰类或属性,这个注解已经过时,不推荐使用

@SuppressWarnings(已定义好的参数)

抑制编译时的警告信息

@Override

注解的使用

public class A{
	public void hello(){
		System.out.println("我是父类的方法");
	}
}

public class B extends A{
	@Override
	public void hello(){
		System.out.println("我是子类的方法,我重写了父类的方法");
	}
}
           

@SuppressWarnings(已定义好的参数)

的使用

@SuppressWarnings("all")
public class A{
	/*这个注解的参数是all
	*意思是抑制所有的警告信息,但对程序没有影响
	*只是让程序员在编写程序的时候舒服一些
	*/
}
           
2、元注解
元注解 作用

@Target()

标识注解使用的范围,内部有设定好的枚举变量,如:TYPE(类),FIELD(属性),METHOD(方法)

@Retention()

注解的保存级别,SOURCE<CLASS<RUNTIME ,一般使用RUNTIME:表示运行时

@Documented

该注解将被包含在javadoc中

@Inherited

子类可以继承父类中的Inherited注解
//设置作用域
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
//设置保存级别
@Retention(RetentionPolicy.RUNTIME)
//设置注解保存在javadoc中
@Documented
//子类可以继承父类中的Inherited注解
@Inherited
           

3、自定义注解

    

@interface

注解名 ,@interface使用后会调用java.lang.Annotation类

注意:接口使用的是

interface

,而注解使用的是

@interface

自定义注解如下:

import java.lang.annotation.*;
import java.util.Arrays;

//设置作用域
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
//设置保存级别
@Retention(RetentionPolicy.RUNTIME)
//设置注解保存在javadoc中
@Documented
//子类可以继承父类中的Inherited注解
@Inherited
//@interface 注解名 ,@interface使用后会调用java.lang.Annotation类
@interface Test1{
    /**
     *name()在这里是属性,不是方法!default是设置默认参数值
     *如果设置的是String name();则使用注解时必须要加参数
     */
    String name() default "";
}
/**
 *@Inherited进行特别讲解
 */
@Test1(name = "小庄")
class Parent{

}
//子类没有写注解,但是继承了父类
class Sun extends Parent{

}
//定义一个测试类进行测试
public class Test{
    public static void main(String[] args){
        //将子类用一个变量操作
        Class c = Sun.class;
        /**
         * c.getAnnotation(Test1.class)-->获取注解Test1
         * 打印使用的注解
         */
        System.out.println((c.getAnnotation(Test1.class)));
    }
}
           

三、反射

什么是反射?

    反射的意思是像镜子一样反射过来,通过反射我们可以根据实例化对象,反射获取这个类的属性、方法、构造器等等内容

Java接口、注解、反射(Java基础系列内容)
1、通过反射获取对象
//Class.forName(类所在的路径。例:包.文件夹.类的名称)
Class c = Class.forName("Test");
System.out.println(c);
           
2、通过反射操作对象

创建一个实体类

public class User{
    private String name;
    public User(){}
    public User(String name) {
        this.name = name; 
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
           

创建测试类通过反射操作对象

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.Exception;
import java.lang.reflect.Method;
//测试类
public class Test {
    public static void main(String[] args) throws Exception{
    	//com是我的包名,User是com包下类名
        Class c = Class.forName("com.User");
        //默认使用无参构造方法进行类加载
        User u1 = (User) c.newInstance();
        //打印结果为User{name='null'}
        System.out.println(u1);
        //以下使用有参构造方法
        //获取一个构造器
      	Constructor constructor = c.getDeclaredConstructor(String.class);
      	//给user设置类加载,并带参数
        Use u2 = (User) constructor.newInstance("小庄");
        //打印结果为User{name='小庄'}
        System.out.println(u2);
        /**
        *通过反射操作类的方法
        */
        //获取User类的setName方法
        Method setName = c.getMethod("setName", String.class);
        //invoke:激活。激活对象u2的方法setName,参数为"小庄2"
        setName.invoke(u2,"小庄2");
        //打印结果为:小庄2
        System.out.println(u.getName());
        /**
        *通过反射操作属性
        */
    	//通过反射获取User的name属性
        Field name = c.getDeclaredField("name");
        //赋予安全权限
        name.setAccessible(true);
        //设置属性的值,u2为User对象,”小庄3为参数“
        name.set(u2,"小庄3");
        //打印结果为:小庄3
        System.out.println(u3.getName());
    }
}
           

四、注解和反射结合使用

package com;
import java.lang.Exception;
import java.lang.reflect.Field;
public class ReflectonAndAnnotation{

    public static void main(String[] args) throws Exception {
        //通过反射获取对象
        Class c = Class.forName("com.User");
        //获取对象的所有注解
        Annotation[] annotations = c.getAnnotations();
        //遍历打印该对象的所有注解
        for (Annotation annotation:annotations){
            System.out.println(annotation);
        }
        //获取指定对象的注解
        Table table =(Table) c.getAnnotation(Table.class);
        //获取该注解中的属性name的值
        String name = table.name();
        //打印注解中的属性name的值
        System.out.println(name);
        //通过对象进行反射获取指定属性:username
        Field username = c.getDeclaredField("username");
        //通过指定属性获得指定的注解内容
        FileName annotation = username.getAnnotation(FileName.class);
        //打印内容
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
    }
}
//类名的注解
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
    String name() ;
}
//属性的注解
@Target(ElementType.FIELD)//属性域
@Retention(RetentionPolicy.RUNTIME)
@interface FileName{
    String columnName();
    String type();
    int length() default 10;
}
@Table(name = "db_user")
class User{
    @FileName(columnName = "db_name",type = "varchar",length = 30)
    private String username;
    @FileName(columnName = "db_age",type = "int",length = 3)
    private Integer age;

    public User(){}

    public User(String username, Integer age) {
        this.username = username;
        this.age = age;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getUsername() {
        return username;
    }
    public Integer getAge() {
        return age;
    }
}
           

上一篇:继承、多态、抽象类

下一篇: 正在更新中…