java筑基.泛型,反射,注解-利用注解加反射练习

2023-05-16

文章目录

  • 泛型:
        • 泛型类
        • 泛型方法
        • 泛型接口
          • 子类明确泛型类的类型参数变量
          • 子类不明确泛型类的类型参数变量
      • 限定类型变量
      • 通配符泛型
  • 注解
    • 元注解
      • 注解的应用场景
  • 反射:
  • 注解+反射练习

泛型:

把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特殊的类型

泛型类


/*
    1:把泛型定义在类上
    2:类型变量定义在类上,方法中也可以使用
 */
public class ObjectTool<T> {
    private T obj;

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }
}
  • 测试代码:

    public static void main(String[] args) {
        //创建对象并指定元素类型
        ObjectTool<String> tool = new ObjectTool<>();

        tool.setObj(new String("字符串"));
        String s = tool.getObj();
        System.out.println(s);


        //创建对象并指定元素类型
        ObjectTool<Integer> objectTool = new ObjectTool<>();
        /**
         * 如果我在这个对象里传入的是String类型的,它在编译时期就通过不了了.
         */
        objectTool.setObj(10);
        int i = objectTool.getObj();
        System.out.println(i);
    }

用户想要使用哪种类型,就在创建的时候指定类型。使用的时候,该类就会自动转换成用户想要使用的类型了。

泛型方法

定义泛型方法…泛型是先定义后使用的


    //定义泛型方法..
    public <T> void show(T t) {
        System.out.println(t);

    }

  • 测试代码:

用户传递进来的是什么类型,返回值就是什么类型了

    public static void main(String[] args) {
        //创建对象
        ObjectTool tool = new ObjectTool();

        //调用方法,传入的参数是什么类型,返回值就是什么类型
        tool.show("hello");
        tool.show(12);
        tool.show(12.5);

    }

泛型接口


/*
    把泛型定义在接口上
 */
public interface Inter<T> {
    public abstract void show(T t);

}

子类明确泛型类的类型参数变量

/**
 * 子类明确泛型类的类型参数变量:
 */

public class InterImpl implements Inter<String> {
    @Override
    public void show(String s) {
        System.out.println(s);

    }
}

子类不明确泛型类的类型参数变量

当子类不明确泛型类的类型参数变量时,外界使用子类的时候,也需要传递类型参数变量进来,在实现类上需要定义出类型参数变量


/**
 * 子类不明确泛型类的类型参数变量:
 *      实现类也要定义出<T>类型的
 *
 */
public class InterImpl<T> implements Inter<T> {

    @Override
    public void show(T t) {
        System.out.println(t);

    }
}

测试代码:

    public static void main(String[] args) {
        //测试第一种情况
        //Inter<String> i = new InterImpl();
        //i.show("hello");

        //第二种情况测试
        Inter<String> ii = new InterImpl<>();
        ii.show("100");

    }

  • 实现类的要是重写父类的方法,返回值的类型是要和父类一样的!
  • 类上声明的泛形只对非静态成员有效

限定类型变量


public class ArrayAlg{

    //表示传入两个泛型,但是需要有compareTo方法 如何实现 使用限定类型变量
    //public static <T> T min(T a,T b){
    //    if(a.compareTo(b)>0) return a : else return b;
    // }
    
    //让 T extends Comparable
    public static <T extends Comparable> T min(T a,T b){
       if(a.compareTo(b)>0) return a : else return b;
     }
     
     
     //可以使用& 跟上接口  也可以extneds类  但是类有且只有一个,接口可以有很多
     public static <T extends ArrayList & Comparable> T min(T a,T b){
       if(a.compareTo(b)>0) return a : else return b;
     }
}

通配符泛型

?是通配符,泛指所有类型

一般用于定义一个引用变量,这么做的好处是,如下所示,定义一个sup的引用变量,就可以指向多个对象。

SuperClass<?> sup = new SuperClass<String>("lisi");

sup = new SuperClass<People>(new People());

sup = new SuperClass<Animal>(new Animal());

//若不用?,用固定的类型的话,则:

SuperClass<String> sup1 = new SuperClass<String>("lisi");

SuperClass<People> sup2 = new SuperClass<People>("lisi");

SuperClass<Animal> sup3 = new SuperClass<Animal>("lisi");

//这就是?通配符的好处。

注解

注解本身没有意义,单独的注解就是一种注释,他需要结合其他如反射,插桩的时候才有作用等技术才有意义.

定义: 使用@interface 关键字声明.

例如:


@Target(ElementType.FIELD)// 属性
@Retention(RetentionPolicy.RUNTIME)// 运行时
public @interface InjectPresenter {
}

或者


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface TestClassAnnotation {
    String id();
//    String value();
    //如果这里不是value 是id那么调用的时候需要id = "22"  value比较特殊
} 



  • @Target(ElementType.TYPE,ElementType.METHOD) 也可以指明多个 在类上注解,在方法上也行

元注解

元注解顾名思义我们可以理解为注解的注解,它是作用在注解中,方便我们使用注解实现想要的功能。元注解分别有

  1. @Retention、 保留级别 只有三个数值 是只在代码中(SOURCE),还是编入class文件中(CLASS),或者是在运行时可以通过反射访问(RUNTIME) SOURCE<CLASS<RUNTIME CLASS包含了SOURCE RUNTIME包含了SOURCE和CLASS
  2. @Target、英文意思是目标,这也很容易理解,使用@Target元注解表示我们的注解作用的范围就比较具体了,可以是类,方法,方法参数变量等,同样也是通过枚举类ElementType表达作用类型
  3. @Document、 的英文意思是文档。它的作用是能够将注解中的元素包含到 Javadoc 中去。
  4. @Inherited和 英文意思是继承,但是这个继承和我们平时理解的继承大同小异,一个被@Inherited注解了的注解修饰了一个父类,如果他的子类没有被其他注解修饰,则它的子类也继承了父类的注解。
  5. @Repeatable(JDK1.8加入)五种。Repeatable使用场景:
    在需要对同一种注解多次使用时,往往需要借助@Repeatable。

Target的英文意思是目标,这也很容易理解,使用@Target元注解表示我们的注解作用的范围就比较具体了,可以是类,方法,方法参数变量等,同样也是通过枚举类ElementType表达作用类型

  • @Target(ElementType.TYPE) 作用接口、类、枚举、注解
  • @Target(ElementType.FIELD) 作用属性字段、枚举的常量
  • @Target(ElementType.METHOD) 作用方法
  • @Target(ElementType.PARAMETER) 作用方法参数
  • @Target(ElementType.CONSTRUCTOR) 作用构造函数
  • @Target(ElementType.LOCAL_VARIABLE)作用局部变量
  • @Target(ElementType.ANNOTATION_TYPE)作用于注解(@Retention注解中就使用该属性)
  • @Target(ElementType.PACKAGE) 作用于包
  • @Target(ElementType.TYPE_PARAMETER) 作用于类型泛型,即泛型方法、泛型类、泛型接口 (jdk1.8加入)
  • @Target(ElementType.TYPE_USE) 类型使用.可以用于标注任意类型除了 class (jdk1.8加入)
    一般比较常用的是ElementType.TYPE类型

注解的应用场景

根据注解的保留级别不同,对注解的使用自然存在不同的场景.

级别技术说明
SOURCE(源码)APT技术在编译器能够获取注解与注解声明的类包括勒种所有成员信息,一般用于生成额外的辅助类
CLASS(字节码)字节码增强/插桩在编译出Class后,通过修改Class数据以实现修改代码逻辑目的. 对于是否需要修改的区分活修改为不同逻辑的判断可以使用注解
RUNTIME(运行时)反射在程序运行期间,通过反射技术动态获取注解

SOURCE<CLASS<RUNTIME CLASS包含了SOURCE RUNTIME包含了SOURCE和CLASS

ide也提供了IntDef注解(元注解),提供语法检查 ide插件实现

IntDef举例:

//设置图片
public  static void setDrawable(int id){
    
}

public static void main(String... args){
    setDrawalbe(111)
}

setDrawalbe 本身应该传入资源图片但是现在传了随手写的int类型.这里可以使用ide提供的注解 @DrawableRes 资源

//设置图片
public  static void setDrawable(@DrawableRes int id){
    
}

public static void main(String... args){
    //setDrawalbe(111) //如果还随手写ide就会提示
}

@DrawableRes 是 AndroidX 定义好的语法检测规则

apt 注解处理器

反射:

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

作用: 能过做到一般做不到的事情. 使用场景: 插件式换肤,插件式开发 apk

反射练习: demo地址

注解+反射练习

通过注解+反射代替activity 通过Intent 传递参数跳转后的 getIntent的方法

比如 A Activity 携带参数

                Intent intent = new Intent();
                intent.setClass(MainActivity.this, JumpActivity.class);
                intent.putExtra("name", "testInject");
                intent.putExtra("age", 18);
                startActivity(intent);

在B Activity只需要如下做就可以自动赋值

 @Autowired("name")
    String mString;

    @Autowired("age")
    int age;
    

利用反射实现自动注入

mString = getintent.getStringExtra("name");
age = getintent.getIntExtra("age")

具体实现代码:

第一个Activity

package com.open.testc;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    private TextView sampleText;
    private Button btJump;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sampleText = (TextView) findViewById(R.id.sample_text);
        btJump = (Button) findViewById(R.id.bt_jump);

        // Example of a call to a native method
        sampleText.setText(stringFromJNI());
        btJump.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                intent.setClass(MainActivity.this, JumpActivity.class);
                intent.putExtra("name", "testInject");
                intent.putExtra("age", 18);
                startActivity(intent);
            }
        });
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
}

第二个Activity

package com.open.testc;

import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.open.testc.inject.Autowired;

public class JumpActivity extends AppCompatActivity {

    private static final String TAG = "JumpActivtiy";
    @Autowired("name")
    String mString;

    @Autowired("age")
    int age;

    private TextView tvResult;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        InjectUtil.InjectView(this);
        setContentView(R.layout.activity_jump);
//        Bundle bundleExtra = getIntent().getBundleExtra();
        Log.d(TAG, "自动装配获取 onCreate: name = " + mString);
        Log.d(TAG, "自动装配获取 onCreate: age = " + age);

        tvResult = (TextView) findViewById(R.id.tv_result);

        tvResult.setText("name = " + mString + " age = " + age);
    }
}

注入工具类:

package com.open.testc;

import android.app.Activity;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.TextUtils;

import com.open.testc.inject.Autowired;

import java.lang.reflect.Field;
import java.util.Arrays;

/**
 * Created by liuml on 2021/4/14 19:40
 */
public class InjectUtil {

    public static void InjectView(Activity activity) {
        Class<? extends Activity> aClass = activity.getClass();
        try {
            //1.遍历这个activity里面所有的GetIntentField 注解
            //getDeclaredFields  和 getFields区别  getDeclaredFields()返回Class中所有的字段,包括私有字段
//        getFields  只返回公共字段,即有public修饰的字段。
            Field[] declaredFields = aClass.getDeclaredFields();
            Bundle bundle = activity.getIntent().getExtras();
            if (bundle == null) {
                return;
            }
            for (Field field : declaredFields) {
                Autowired annotation = field.getAnnotation(Autowired.class);
                //2. 找到注解后获取他的值
                if (field.isAnnotationPresent(Autowired.class)) {
                    //获得key
                    String key = TextUtils.isEmpty(annotation.value()) ? field.getName() : annotation.value();

                    if (bundle.containsKey(key)) {
                        //获取传输的值
                        Object obj = bundle.get(key);

                        //获得数组单个元素类型 下面需要用到
                        Class<?> componentType = field.getType().getComponentType();
                        //判断如果是Parcelable[] 素组
                        if (field.getType().isArray() && Parcelable.class.isAssignableFrom(componentType)) {
                            //创建对应类型并拷贝
                            Object[] objs = (Object[]) obj;//强转
                            //拷贝数据  (Class<? extends Object[]>) field.getType())   通过getType 获取真正的反射类型
                            Object[] objects = Arrays.copyOf(objs, objs.length, (Class<? extends Object[]>) field.getType());
//                            Object[] objects = Arrays.copyOf(objs, objs.length, Parcelable[].class);
                            obj = objects;//赋值
                        }

                        //3. 反射设置属性的值
                        field.setAccessible(true);
//                    Class<?> type = field.getType();
                        field.set(activity, obj);
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();

        }
    }
} 

ASM插件安装 使用字节码插桩技术时这个插件很有用

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java筑基.泛型,反射,注解-利用注解加反射练习 的相关文章

  • unity寻路插件(A* Pathfinding)小结

    A Pathfinding 详细使用教程 基本功能 1 astarpath cs 核心组件 xff0c 相当于 路 xff0c 场景里应该只存在一个 2 Seeker cs 相当于一个代理 xff0c 寻找路径 xff0c 需要绑定在每一个
  • Socket网络通信C++编程总结

    概述 Socket编程有三种 xff0c 流式套接字 xff08 SOCK STREAM xff09 数据报套接字 SOCK DGRAM 原始套接字 SOCK RAW 前两者较常用 xff0c 这里简单总结前两种编程步骤以及一些参考资料 编
  • 【STM32+cubemx】0029 HAL库开发:HMC5883L磁力计的应用(电子指南针)

    今天我们来学习电子磁力计HMC5883L的使用 先介绍磁力计的基础知识 xff0c 再给一个获取磁力计数据的例子 xff0c 最后讲解HMC5883L磁力计的校准 xff0c 以及一些使用中的经验 1 xff09 HMC5883L磁力计的基
  • stm32F103R6之BKP(备份寄存器)

    目录 概述 侵入检测 RTC校准 概述 Stm32F103有42个16位的备份寄存器 他们处在备份域里 xff0c 当VDD电源被切断 xff0c 他们仍然由VBAT维持供电 当系统在待机模式下被唤醒 xff0c 或系统复位或电源复位时 x
  • Stm32F103R6之控制器局域网

    目录 概述 双CAN bxCAN工作模式 CAN协议特点 xff1a ISO11898标准CAN物理特性 CAN协议帧 概述 bxCAN是基本扩展CAN Basic Extended CAN 的缩写 xff0c 它支持CAN协议2 0A和2
  • 如何输出一个数的二进制数

    实现思想 xff1a 二进制数是以bit为操作数 xff0c 所以要想将一个数转换为二进制数 xff0c 我们需要先要将输入的数字转化为二进制数 xff0c 然后从高位到低位判断每一位是 1 还是 0 xff0c 最后把对应的 1 和 0
  • 使用libcurl库编写HTTP客户端(包括GET/POST/HTTPS)

    最近在写一个应用程序 需要与HTTP服务器进行数据交互 于是乎自己写了一个类似wget的功能的客户端 实现很简单 但是功能不给力 只可基本功能 于是又在网上找了找 发现使用libcurl库很方便 很强大 比起wget之类的 强大不是一点点
  • 修改系统默认shell为bash

    xfeff xfeff 从 ubuntu 6 10 开始 xff0c ubuntu 就将先前默认的bash shell 更换成了dash shell xff1b 其表现为 bin sh 链接倒了 bin dash而不是传统的 bin bas
  • 如何解决Reporting Services目录数据库文件存在的问题

    出处 xff1a http blog sina com cn s blog 6bace3cc0101jlxv html 错误提示 xff1a 自检时提示 Reporting Services目录数据库文件存在 失败 xff0c Report
  • 无线射频专题《射频合规,2.4GHz WIFI测试指标详解》

    目录 引言 Transmitter Power 发送功率 Transmit Spectrum Mask 发送信号频谱模版 Frequency Error 频率误差 EVM 矢量误差幅度 Band Edges and harmonics 频带
  • 获取当前访问的路径

    String returl 61 request getRequestURL 43 request getQueryString 61 61 null 34 34 34 34 43 request getQueryString
  • 抓取百度关键词排名

    最近在做百度关键词排名的功能 xff0c 发现网上资源比较少 xff0c 于是自己琢磨了一下 xff0c 写一下笔记 xff1b 本文重点在于提供思路 xff0c 请不要过分依赖 xff0c 本文主要靠抓取页面标签来完成 xff0c 如果百
  • 抓取百度关键词排名、标题、连接、描述

    抓取百度关键词排名 标题 连接 描述 转载请标明出处 最近在做百度关键词排名的功能 xff0c 发现网上资源比较这里写代码片少 xff0c 于是自己琢磨了一下 xff0c 写一下笔记 xff1b 本文重点在于提供思路 xff0c 请不要过分
  • Windows Server 2008远程桌面端口的修改

    Windows Server 2008远程桌面端口系统默认的是3389端口 xff0c 但出于安全考虑 xff08 谁都不希望任何都可以远程连接到自己的服务器吧 xff0c 哈哈 xff09 xff0c 经常我们把系统默认的3389端口更改
  • jsp 登陆成功后,显示登录的用户名

    首先在登陆界面将用户名保存起来 xff0c 我这里是将用户名提交到Servlet然后再进行保存 xff0c 从登录界面取用户参数 String uname 61 request getParameter 34 userName 34 req
  • 背景图片随网页的变化而变化(指大小)

    lt DOCTYPE HTML PUBLIC 34 W3C DTD HTML 4 01 Transitional EN 34 gt lt html xmlns 61 34 http www w3 org 1999 xhtml 34 gt l
  • 为什么vscode用久了电脑速度变慢?

    1 vscode 插件占用的内存 1 已经安装的插件 2 插件占用内存 我可以看到 xff0c vs code 这个程序下面有多个进程在跑 xff0c 插件占用的内存比我电脑剩下所有占用的内存还要高 xff0c 但是vs code 性能还是
  • ROS基础学习(一)---创建工作空间

    工作空间 xff08 workspace xff1a 是一个存放工程开发相关文件的文件夹 src xff1a 代码空间 xff08 Source Space build 编译空间 xff08 Build Space devel 开发空间 x
  • 一个简单的爬虫程序,爬取网站的图片

    最简单的爬虫是分析网页 xff0c 如果要爬取图片 xff0c 就要将图片在网页中的格式进行分析 xff0c 取到图片的连接 xff0c 接着下载图片 xff1b 由于网页中还会链接到其他的网页 xff0c 所以需要将其中的所有网页取出 x
  • python文件操作及引申的代码行数统计

    文件操作一般包括文件的读写 xff0c 文件夹的创建 xff0c 文件夹的删除等 第一部分 xff1a python文件读写的基本操作 python打开文件一般使用 open函数 xff1a open file mode 61 39 r 3

随机推荐

  • 超声波测距仪

    基本原理 超声波是利用反射的原理测量距离的 xff0c 被测距离一端为超声波传感器 xff0c 另一端必须有能反射超声波的物体 测量距离时 xff0c 将超声波传感器对准反射物发射超声波 xff0c 并开始计时 xff0c 超声波在空气中传
  • Authorization 值中Bearer空格加token值在python接口请求中如何实现

    在项目中每个接口请求都需要Authorization 值 xff0c 而Authorization他的值必须 Bearer 加token值 xff0c 刚开始自己忘记添加Bearer 接口请求一直拒绝访问 xff0c 后来用fiddler抓
  • printf格式化字符串漏洞原理解析

    读任意地址 printf 34 x 34 只给格式化字符串 xff0c 而不给参数 xff0c 会导致内存泄漏从而读到内存中其他地址的数据 N x参数可以以16进制方式打印第N个参数的内容 xff0c 通过修改N xff0c 我们可以遍历栈
  • 教程丨利用微软官方工具制作U盘安装Win10系统

    一 制作Win10安装U盘 1 登录网站 https www microsoft com zh cn software download windows10 下载 MediaCreationTool 工具 xff0c 这里我们直接点击 立即
  • Linux常用命令大全

    发布jar包 nohup java jar xxxx jar gt dev null 2 gt amp 1 amp 修改nginx conf 后刷新配置 usr local nginx sbin nginx t 测试配置文件修改是否正常 u
  • Zab协议详解

    什么是Zab协议 xff1f Zab协议 的全称是 Zookeeper Atomic Broadcast xff08 Zookeeper原子广播 xff09 Zookeeper 是通过 Zab 协议来保证分布式事务的最终一致性 Zab协议是
  • 谷歌浏览器安装json格式化插件

    实际开发工作中经常用到json数据 xff0c 那么就会有这样一个需求 xff1a 在谷歌浏览器中访问URL地址返回的json数据能否按照json格式展现出来 比如 xff0c 在谷歌浏览器中访问 xff1a http jsonview c
  • Seata详解(一)

    分布式事务 事务是数据库的概念 xff0c 数据库事务 xff08 ACID xff1a 原子性 一致性 隔离性和持久性 xff09 xff1b 分布式事务的产生 xff0c 是由于数据库的拆分和分布式架构 微服务 带来的 xff0c 在常
  • RocketMQ的事务消息和改造

    什么是 rmq分布式事务消息 xff1f Apache RocketMQ在4 3 0版中已经支持分布式事务消息 xff0c 这里RocketMQ采用了2PC的思想来实现了提交事务消息 xff0c 同时增加一个补偿逻辑来处理二阶段超时或者失败
  • session和token区别

    一 session的状态保持及弊端 xff08 1 xff09 当用户第1次通过浏览器使用用户名和密码访问服务器时 xff0c 服务器对用户名和密码进行验证 xff08 2 xff09 验证成功后 xff0c 在服务器端生成并保存sessi
  • 关于阿里云对RocketMQ的topic,tag,consumer关系的理解

    什么是订阅关系一致 消息队列RocketMQ版 阿里云帮助中心 RocketMQ 中Topic Tag GroupName基本概念介绍 Young丶的博客 CSDN博客 rocketmq topic和group的区别 转载
  • MySql Workbench 8.0汉化插件分享

    打开workbench的安装数据目录 xff0c 路径是 xff1a C Program Files MySQL MySQL Workbench 8 0 CE data 打开以后 xff0c 可以看到下面有一堆的xml结尾的文件 xff0c
  • Java-Jdk12版本下载后没有Jre的解决方案以及配置环境变量

    新本Jdk12版本下载后不像以前的版本会自动生成Jre文件夹 xff0c 通过dos命令行可以解决 1 下载jdk12 网址 xff1a https www oracle com technetwork java javase downlo
  • android--性能优化1--首屏优化&启动速度与执行效率检测

    文章目录 实战篇traceview 工具使用操作步骤操作步骤2 systrace 工具使用操作步骤 AOP 工具 hugo 的使用使用方法效果 BlockCanary 使用AOP 工具使用 AspectJ操作步骤 优化方案 异步线程优化 针
  • error Failed connect to github.com 443原因 Github更换认证方式

    Github更换认证方式 github近期调整了认证方式 xff0c 不再允许第三方工具基于账号密码来访问和管理项目了 除非使用github DeskTop 自带的客户端 好坑啊 我一直再用android studio 自带的提交工具很方便
  • AppCompatRatingBar备份用 下次拷贝直接用自定义图片背景

    控件 lt androidx appcompat widget AppCompatRatingBar android id 61 34 64 43 id rating bar 34 style 61 34 64 style myRating
  • 备份Edittext编辑框字数限制ui以及逻辑

    ui布局 etContent addTextChangedListener new TextWatcher 记录输入的字数 private CharSequence enterWords private int selectionStart
  • android—性能优化2—内存优化

    文章目录 性能优化 工具 memory profilerLeakCanaryarthookepic 库 java内存管理机制java 内存回收机制Android内存管理机制Dalvik与 Art区别Low Memory Killer 内存抖
  • glide4.11.0封装gfilib优化gif图片加载

    文章目录 具体步骤 下载giflib 和 framesequence导入并集成 giflib 和 framesequenceglide的配置gif使用giflib集成开始使用加载思路创建自定义GifDrawable 需求 目前项目中加载进度
  • java筑基.泛型,反射,注解-利用注解加反射练习

    文章目录 泛型 泛型类泛型方法泛型接口子类明确泛型类的类型参数变量子类不明确泛型类的类型参数变量 限定类型变量通配符泛型 注解元注解注解的应用场景 反射 注解 43 反射练习 泛型 把类型明确的工作推迟到创建对象或调用方法的时候才去明确的特