Java笔记(JUnit、反射、注解)
创始人
2024-02-06 12:13:11
0

一、JUnit单元测试


1. JUnit的介绍


JUnit是一个Java语言的单元测试工具。有了它我们在开发阶段就可以对自己编写的功能模块进行单元测试(就是一块一块去测试),看看是否达到具体预期(这样小Bug我们自己就能解决)。

黑盒测试:不需要写代码,给定输入值,看程序是否能够输出期望的值。

白盒测试:需要写代码的。关注程序具体的执行流程。

在这里插入图片描述

JUnit通过注解识别测试方法:@Test@Before@After

  • @Test:用于修饰需要执行的测试方法。
  • @Before:修饰的方法会在测试方法之前被自动执行。
  • @After:修饰的方法会在测试方法执行之后自动被执行。

JUnit以上三种单元测试方法的注意事项:

  • 测试方法不能是静态方法。
  • 测试方法不能有返回值。
  • 测试方法不能有参数。


2. JUnit的使用


1、下载JUnit相关的jar包

junit-4.12下载地址: junit-4.12 https://mvnrepository.com/artifact/junit/junit/4.12

hamcrest-core下载地址: https://mvnrepository.com/artifact/org.hamcrest/hamcrest-core/1.3

在这里插入图片描述


2、在模块下面创建一个lib目录,用于存放jar包

在这里插入图片描述


3、选中lib目录并鼠标右键,然后找到【Add as Library】并点击,将jar包添加到模块中。

在这里插入图片描述

在这里插入图片描述


4、创建一个测试类,编写测试方法,分别@Test、@Before、@After注解修饰。

/*** Junit快速入门* @author 白豆五* @version 2022/11/19 22:05* @since JDK8*/
public class JUnitTest {// 定义静态成员变量 便于让测试方法访问private static List list = new ArrayList<>();// 在测试方法之前执行@Beforepublic void init() {list.add(111);list.add(222);list.add(13);list.add(25);list.add(16);}//测试方法@Testpublic void test() {list.sort(new Comparator() {@Overridepublic int compare(Integer o1, Integer o2) {return o1 - o2;}});}// 在测试方法之后执行@Afterpublic void print() {System.out.println(list);}
}

在这里插入图片描述

二、反射(Reflection)


1. 类加载器


1.1 类加载器的时机

当程序运行之后,第一次使用某个类的对象,类加载器(ClassLoader)会将该类的.class文件从磁盘加载到内存中,然后将该类的信息(如 成员变量、成员方法、构造方法)存储到 java.lang.Class对象中。

在这里插入图片描述


什么时候类加载器会将类的字节码文件加载到内存,并使用Class对象存储类的相关信息?

1、创建类的实例。

2、使用类的静态变量。

3、使用这个类的静态方法。

4、使用反射的方式创建某个类或者接口的对应Class对象。

5、初始化某个类的子类。

6、使用java命令运行某个主类(带main方法的类)。

public class TestClassLoder {/*** 类加载器的时机*/@Testpublic void testClassLoder() {// Animal animal = new Animal(); // 1、创建类的实例// Animal.color="red";           // 2、使用类调用静态成员变量// Animal.print();               // 3、使用类调用静态方法/*try {// 4、通过反射加载这个类获取字节码对象Class clazz = Class.forName("com.baidou.p3_loder_time.Animal");} catch (ClassNotFoundException e) {e.printStackTrace();}*/// 5、初始化子类Animal dog = new Dog();}
}class Animal {// 静态成员变量static String color = "blue";// 静态代码块在类加载的时候会被执行,而且只会执行一次static {System.out.println("执行了Animal的静态代码块");}// 静态方法static void print() {System.out.println(color);}
}class Dog extends Animal {}

1.2 类加载器的分类

Java中有三种不同的类加载器(ClassLoader)用于加载不同种类的class文件:(JDK8)

1、BootstrapClassLoader:根类加载器,也被称为引导类加载器。

  • 负责Java核心类库的加载(如 jdk1.8.0_201\jre\lib\rt.jar)

    在这里插入图片描述

  • 它是用C++编写的,是JVM自带的类加载器。

  • 该加载器无法直接获取。(如 System、String获取加载器返回的值为null)


2、ExtClassLoader:扩展类加载器。

  • ***负责加载JRE的扩展目录中的jar包。***(如 jdk1.8.0_201\jre\lib\ext)
    在这里插入图片描述

3、AppClassLoader:系统类加载器/应用类加载器。

  • Java语言编写的类加载器,用于加载我们定义的类和第三方jar包中的类

类加载器加载机制

双亲委派机制: 谁用谁加载。

当加载类的时候,首先会问委托父加载器(如AppClassLoader)它负不负责加载,如果它不会则继续向上找。但是不管是谁加载 .class文件只能被加载一次。

在这里插入图片描述
这三个类加载器之间不存在继承关系,ClassLoader是的他们的最终父类。


1.3 如何获取类加载器

用Class对象.getClassLoader()方法获取类加载器。

在这里插入图片描述
在这里插入图片描述

import org.junit.Test;
import sun.net.spi.nameservice.dns.DNSNameService;/*** 获取类加载器* @author 白豆五* @version 2022/11/21 19:49* @since JDK8*/
public class Demo04ClassLoder {/*** 获取根类加载器*/@Testpublic void boot() {// String类 是核心类库rt.jar里的 由BootstrapClassLoader负则加载// 获取String类的Class对象Class clazz = String.class;// 获取类加载器对象ClassLoader classLoader = clazz.getClassLoader();System.out.println(classLoader);// BootstrapClassLoader是根类加载器是C++编写,不让我们直接获取,所以返回值为null}/*** 获取扩展加载器*/@Testpublic void ext() {// DNSNameService是扩展类  由ExtClassLoader负则加载// 获取DNSNameService类的Class对象Class clazz = DNSNameService.class;// 获取类加载器对象ClassLoader classLoader = clazz.getClassLoader();System.out.println(classLoader);//sun.misc.Launcher$ExtClassLoader@28a418fc}/*** 获取应用类加载器*/@Testpublic void app() {// Demo04ClassLoder类是自己编写的类  由AppClassLoader负则加载// 获取Demo04ClassLoder类的Class对象Class clazz = Demo04ClassLoder.class;// 获取类加载器对象ClassLoader c1 = clazz.getClassLoader();System.out.println(c1);//sun.misc.Launcher$AppClassLoader@18b4aac2// 获取应用类加载器的委托父加载器对象(扩展类加载器)ClassLoader c2 = c1.getParent();System.out.println(c2);//sun.misc.Launcher$ExtClassLoader@28a418fc// 获取扩展类加载器的委托父加载器对象(根类加载器)ClassLoader c3 = c2.getParent();System.out.println(c3);//因他是c++编写不让直接获取,所以拿到的是null}
}

在这里插入图片描述


2. 反射的介绍


原文:https://blog.csdn.net/weixin_42298270/article/details/113371164


反射机制指的是程序在运行时能够获取自身的信息。在Java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息。
要使用一个类,就要先把它加载到虚拟机中,生成一个Class对象。这个Class对象就保存了这个类的一切信息。反射机制的实现,就是获取这个Class对象,通过Class对象去访问类、对象的元数据以及运行时的数据。

反射是一种机制,利用该机制在程序运行的过程中,对类进行解剖并且去操作类的成员(成员变量,成员方法,构造方法)。要想使用反射,就必须要获取该类的字节码对象(也叫Class对象)。

反射的应用场景:如主流的开发框架(如spring-frammework、mybaits等等)、IDEA(智能化的语法提示等等)。


3. Class类的对象


Class类也是有对象的,但是程序员无法自己创建,由JVM帮助创建,程序员可以获取到该Class类型的对象,从而完成相关的操作。

3.1. 获取Class对象的三种方法

  • 方式一:Class c1 = Class.forName("类的全名称,即包名.类名");, forName是Class类的静态方法。
  • 方式二:Class c2 = 类名.class属性,每个类都默认有一个class属性。
  • 方式三:Class c3 = 对象.getClass();,getClass是Object类的方法。

pojo类:

public class User {private String name;private int age;//空参构造public User() {}//满参public User(String name, int age) {this.name = name;this.age = age;}//只给name赋值public User(String name) {this.name = name;}//只给age赋值private User(int age) {this.age = age;}private char[] my2CharArray(String str) {return str.toCharArray();}public int getSum(int a, int b) {return a + b;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

测试类:

/*** 获取Class对象** @author 白豆五* @version 2022/11/21 21:49* @since JDK8*/
public class Demo04GetClass {/*** 方式一:对象.getClass()获取对应的字节码对象*/@Testpublic void test1(){User user = new User();Class c1 = user.getClass();//调用Class类的toString()方法System.out.println(c1); //class com.baidou.pojo.User}/*** 方式二:类名.class属性获取对应的字节码对象*/@Testpublic void test2(){Class c2 = User.class;//调用Class类的toString()方法System.out.println(c2); //class com.baidou.pojo.User}/*** 方式三:Class.forName()获取对应的字节码对象*/@Testpublic void test3() throws ClassNotFoundException {Class c3 = Class.forName("com.baidou.pojo.User");System.out.println(c3); //class com.baidou.pojo.User}/*** 基本数据类型,也有对应的Class对象*/@Testpublic void test4(){Class c1 = int.class;System.out.println(c1); //int}
}

3.2 Class类的常用方法

下面的成员方法都是通过与类关联的Class对象调用。

  • public String getName():获取类的全路径名,即包名+类名。
  • public String getSimpleName():获取类的类名(类名、接口名、注解名等等)。
  • public T newInstance()throws InstantiationException, IllegalAccessException:使用反射的方式创建对象,会调用该类的无参构造方法,如果该类没有无参构造方法会报 InstantiationException(实例化异常)
/*** Class类的常用方法*/
@Test
public void testClassNewInstance()  {// 获取Animal类的字节码对象Class animalClass = Animal.class;String name = animalClass.getName();  //获取Animal类的全路径名,包名+类名System.out.println(name); //com.baidou.p3_loder_time.AnimalSystem.out.println(animalClass.getSimpleName()); //获取类名try {// 反射的方式创建animal对象Animal animal = animalClass.newInstance();System.out.println(animal);} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}

在这里插入图片描述

Java源程序通过编译会生成字节码文件,字节码文件会被类加载器加载到内存方法区中,同时针对.class文件创建一个Class类型的对象(存储类的信息),然后该对象被保存到堆内存中。这个Class对象里面封装了操作构造器、成员方法、成员变量的api,这样我们通过反射可以操作.class文件中成员变量、成员方法、构造方法啦。


4. 反射获取构造方法(Constructor)


反射获取构造方法的步骤:
         1、获取类的Class对象
         2、Class对象.get构造器的方法。

4.1 获取构造方法

1、返回一个public修饰的指定参数构造方法,不传参默认调用无参构造方法。

public Constructor getConstructor(Class... parameterTypes) throws NoSuchMethodException,SecurityException                                             

2、返回多个public修饰的构造方法。

public Constructor[] getConstructors() throws SecurityException

3、返回一个任意修饰符的指定参数构造方法。

//返回一个任意修饰符的指定参数构造方法
public Constructor getDeclaredConstructor(Class... parameterTypes) throws NoSuchMethodException,SecurityException      // 暴力反射
//java.lang.reflect.AccessibleObject类,成员方法:
public void setAccessible(boolean flag)// 参数:true,取消 Java 语言访问检查        private 失效// 参数:false,实施 Java 语言访问检查       private 有效    
// 私有构造方法对象调用setAccessible()方法,取消Java语言访问检查
constructor.setAccessible(true);//Constructor,Field,Method类,都可以调用setAccessible方法,进行暴力反射                     

4、返回多个任意修饰符的构造方法。

public Constructor[] getDeclaredConstructors() throws SecurityException

示例:

public class User {private String name;private int age;//空参构造public User() {}//满参public User(String name, int age) {this.name = name;this.age = age;}//只给name赋值public User(String name) {this.name = name;}//只给age赋值private User(int age) {this.age = age;}private char[] my2CharArray(String str) {return str.toCharArray();}public int getSum(int a, int b) {return a + b;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

(1) 获取public修饰的所有构造方法对象

/*** 获取public修饰的所有构造方法对象*/
@Test
public void test1() throws ClassNotFoundException {//获取类的Class对象Class c1 = Class.forName("com.baidou.pojo.User");//取public修饰的所有构造方法对象for (Constructor cons : cons1) {System.out.println(cons);}
}

在这里插入图片描述

(2) 获取所有构造方法对象(包含private修饰的)

/*** 获取所有构造方法对象(包含private修饰的)*/
@Test
public void test2() throws ClassNotFoundException {//获取类的Class对象Class c2 = Class.forName("com.baidou.pojo.User");// 获取所有构造方法对象(包含private修饰的)Constructor[] cons2 = c2.getDeclaredConstructors();for (Constructor constructor : cons2) {System.out.println(constructor);}
}

在这里插入图片描述


(3) 获取public修饰的空参构造方法对象

/*** 获取public修饰的空参构造方法对象*/
@Test
public void test3() throws Exception {//获取类的Class对象Class c3 = Class.forName("com.baidou.pojo.User");//获取public修饰的空参构造方法对象Constructor cons3 = c3.getConstructor();System.out.println(cons3);
}

在这里插入图片描述


(4) 获取public修饰的第一个参数是String类型,第二个参数是int类型的构造方法对象

/*** 获取public修饰的第一个参数是String类型,第二个参数是int类型的构造方法对象*/
@Test
public void test4() throws Exception {//获取类的Class对象Class c4 = Class.forName("com.baidou.pojo.User");//获取public修饰的第一个参数是String类型,第二个参数是int类型的构造方法对象Constructor cons4 = c4.getConstructor(String.class,int.class);System.out.println(cons4);
}

在这里插入图片描述


(5) 获取private修饰的参数是int类型的构造方法对象

/*** 获取private修饰的参数是int类型的构造方法对象*/
@Test
public void test5() throws Exception {//获取类的Class对象Class c5 = Class.forName("com.baidou.pojo.User");//获取private修饰的参数是int类型的构造方法对象Constructor cons5 = c5.getDeclaredConstructor(int.class);System.out.println(cons5);
}

在这里插入图片描述


4.2 执行构造方法创建具体对象

1、调用java.lang.reflect.Constructor类中的newInstance()方法:

// 根据方法参数传递的具体数据,调用指定的构造方法,从而创建一个具体的对象
// 可变参数 可以是0个或多个 ,Object[] 
public T newInstance(Object ... initargs)

2、快捷方式:Class对象.newInstance()方法,调用该类的无参构造方法创建对象,如果该类没有无参构造方法会报 InstantiationException(实例化异常)。

public T newInstance()throws InstantiationException, IllegalAccessException

示例:反射获取空参构造方法并运行

/**
* 反射获取空参构造方法并运行
*/
@Test
public void newInstance1() throws Exception {// 获取字节码对象Class clazz = Class.forName("com.baidou.pojo.User");// 反射获取空参构造方法对象Constructor con = clazz.getConstructor();// 执行空参构造方法对象,创建具体的实例User user = (User) con.newInstance();System.out.println(user);
}

在这里插入图片描述


示例:反射带参构造方法并运行

/**
* 反射带参构造方法并运行
*/
@Test
public void newInstance2() throws Exception {// 获取字节码对象Class clazz = Class.forName("com.baidou.pojo.User");// 反射获取满参构造方法对象 public User(String name,int age)Constructor con = clazz.getConstructor(String.class,int.class);// 执行满参构造方法对象,创建具体的实例User user = (User) con.newInstance("白豆五",18);System.out.println(user);}

在这里插入图片描述


示例:反射创建对象的快捷方式

/*** 反射创建对象的快捷方式*/
@Test
public void newInstance3() throws Exception {// 获取字节码对象Class clazz = Class.forName("com.baidou.pojo.User");// 反射创建对象的快捷方式 class对象.newInstance()方法Object obj =  clazz.newInstance();System.out.println(obj);
}

在这里插入图片描述


示例:反射获取私有构造方法并运行

/**
* 反射获取私有构造方法并运行
*/
@Test
public void newInstance4() throws Exception {// 获取字节码对象Class clazz = Class.forName("com.baidou.pojo.User");// 反射获取私有构造方法对象 p private User(int age)Constructor con1 = clazz.getConstructor( int.class);// 执行私有构造方法对象,创建具体的实例User user = (User) con1.newInstance( 18);System.out.println(user);}

在这里插入图片描述

解决方案:使用getDeclaredConstructor()方法获取私有方法

/*** 反射获取私有构造方法并运行*/
@Test
public void newInstance4() throws Exception {// 获取字节码对象Class clazz = Class.forName("com.baidou.pojo.User");// 反射获取私有构造方法对象 p private User(int age)// Constructor con1 = clazz.getConstructor( int.class); //NoSuchMethodExceptionConstructor con2 = clazz.getDeclaredConstructor(int.class);// 执行私有构造方法对象,创建具体的实例User user = (User) con2.newInstance( 18);System.out.println(user);}

在这里插入图片描述
解决方案:取消访问检查

/*** 反射获取私有构造方法并运行*/
@Test
public void newInstance4() throws Exception {// 获取字节码对象Class clazz = Class.forName("com.baidou.pojo.User");// 反射获取私有构造方法对象 p private User(int age)// Constructor con1 = clazz.getConstructor( int.class); //NoSuchMethodExceptionConstructor con2 = clazz.getDeclaredConstructor(int.class);con2.setAccessible(true); // 取消访问检查// 执行私有构造方法对象,创建具体的实例User user = (User) con2.newInstance( 18);System.out.println(user);
}

在这里插入图片描述



5. 反射获取成员变量(Field)


反射第一步先得到类对象,然后从类对象中获取类的成分对象。

Class类中获取成员变量的方法如下:

  • Field[] getFields():返回所有成员变量对象的数组(只能拿public的)。

  • Field[] getDeclaredFields():返回所有成员变量对象的数组,存在就能拿到。

  • Field getField(String name):返回单个成员变量对象(只能拿public的)。

  • Field getDeclaredField(String name):返回单个成员变量对象,存在就能拿到。


Field类中取值、赋值的方法如下:

  • void set(Object obj,Object value):为Field对象赋值。
  • Object get(Object obj):获Field对象的取值。

示例:反射获取成员变量

User.java

public class User {private String name;private int age;//空参构造public User() {}//满参public User(String name, int age) {this.name = name;this.age = age;}//只给name赋值public User(String name) {this.name = name;}//只给age赋值private User(int age) {this.age = age;}private char[] my2CharArray(String str) {return str.toCharArray();}public int getSum(int a, int b) {return a + b;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
/*** 反射获取成员变量*/
@Test
public void testFiled() throws Exception {// 获取Class对象Class clazz = User.class;// 快捷方式创建对象User user = clazz.newInstance();// 获取私有Field对象Field f1 = clazz.getDeclaredField("name");Field f2 = clazz.getDeclaredField("age");f1.setAccessible(true); //取消访问检查f2.setAccessible(true); //取消访问检查f1.set(user, "张三");                  //为name属性赋值f2.set(user, 18);                     //为age属性赋值String name = (String) f1.get(user);  //取值int age = (int) f2.get(user);         //取值System.out.println(name + "::" + age);
}

在这里插入图片描述

注意:如果某成员变量是非public的,需要打开权限(暴力反射,setAccessible(true)),然后再取值、赋值。



6. 反射获取方法(Method)


也是通过Class对象拿Method对象。

Class类中获取成员方法的方法如下:

  • Method[] getMethods():返回所有成员方法对象的数组(只能拿public的)。

  • Method[] getDeclaredMethods():返回所有成员方法对象的数组,存在就能拿到。

  • Method getMethod(String name,Class...parameterTypes):返回单个成员方法对象(只能拿public的)。

  • Method getDeclaredMethod(String name,Class...parameterTypes):返回单个成员方法对象,存在就能拿到。


Method类中用于触发执行的方法如下:

  • Object invoke(Object obj, Object... args): 运行方法。
    • 参数一:用obj对象调用该方法。
    • 参数二:调用方法的传递的参数(如果没有就不写)。
    • 返回值:方法的返回值(如果没有就不写)。

示例1:获取setName()、getName()、toString()方法并执行。

/*** 获取setName()、getName()、toString()方法并执行* public String getName()* public void setName(String name)* public String toString()*/
@Test
public void testgetMethoods() throws Exception {// 获取Class对象Class clazz = User.class;// 快捷方式创建对象User user = clazz.newInstance();// 获取Method对象Method setName = null;Method getName = null;Method toString = null;Method[] methods = clazz.getMethods();for (Method method : methods) {switch (method.getName()) {case "setName":setName = method;break;case "getName":getName = method;break;case "toString":toString = method;break;}}// System.out.println(setName);// System.out.println(getName);// System.out.println(toString);// 执行Method对象对应的方法setName.invoke(user,"张三");Object name = getName.invoke(user);System.out.println(name);Object tostr = toString.invoke(user);System.out.println(tostr);
}

在这里插入图片描述



三、注解(Annotation)


1. 什么是注解?


  • 注解(Annotation): 也叫元数据。一种代码级别的说明。
  • 它是JDK5.0引入的一个新特性,与类、接口、枚举是在同一个层次。
  • 它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,标注/注释(comment)。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


2. 注解的作用


  • 编写文档:通过代码里标识的注解生成文档。(例如,生成文档javadoc文档)
  • 代码分析:通过代码里标识的注解对代码进行分析。(例如,注解的反射)
  • 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查。(例如,Override覆盖重写)

3. 常见注解


  • @author:用来标识作者名。
  • @version:用于标识对象的版本号,适用范围:文件、类、方法。
  • @Override:用来修饰方法声明,告诉编译器该方法是重写父类中的方法,如果父类不存在该方法,则编译失败。
  • @FunctionalInterface: 检测是否是函数式接口(JDK8新特性)。
  • @Deprecated:可以用来注解类、接口、成员方法和成员变量等,用于表示某个元素(类、方法等)已过时。当其他程序使用已过时的元素时,编译器将会给出警告(删除线 )。
  • @SuppressWarnings:取消显示指定的编译器警告。
    • @SuppressWarnings(value=“all”):抑制所有警告。
    • @SuppressWarnings(value=“deprecation”): 抑制过期方法警告。


4. 自定义注解


自定义注解就是自己做一个注解来玩玩。

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口。

自定义注解的格式:

public @interface 注解名 {属性集// public 属性类型 属性名() default 默认值;            
}// 空注解: 没有任何属性 	
/*
有属性集的注解: 属性的定义格式一:数据类型 属性名(); 没有默认值的属性属性的定义格式二:数据类型 属性名() default 默认值; 有默认值的属性型对应的一维数组
*/	
//注解属性可以选择的数据类型:8种基本类型,String类型,枚举类型,注解类型,Class类型以及以上任意类
// 空注解
public @interface MyTest {//没有任何属性 
}//定义有属性集的注解
public @interface MyTest2  {String name();//String 类型的属性 name,没有默认值int age() default 18;//int 类型的属性 age,默认值 18String[] hobbies();//String 类型的数组 hobbiesMyAnno01 myAnno01();//注解类型
}

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...