反射-单元测试-jar包生成-Scanner复习

反射:

反射:解剖一个类(变量(Field)、方法(Method)、构造方法(Constructor))。

Java反射在程序运行的过程中,可以对任意一个类型进行任意的操作,例如:加载任意类型,调用类型的任意方法,获取任意的成员变量、构造方法,可以创建该类的对象。

如果要获取一个类型的各种内容,首先要获得这个类的字节码对象

解剖这个类,获取成员,需要使用Class类型。

这种动态的获取信息以及动态访问成员的这种方式,称为反射

获取类的字节码对象(Class类型的对象)的三种方式:

对象名.getClass():返回某个引用指向的具体对象所属的运行类的字节对象。获取到的是那个真正用于创建对象的字节码对象。

类名.class:如果已经有类名,可以通过类名.class的方式来获取这个类的字节码对象。

通过Class.forName(类的全路径):Class中的一个静态方法,可以根据传一个类的全类名,动态地加载某个类型,可以获取该类的字节码对象,扩展性强。

解剖成员变量

Field

getField(String name) 

返回一个 Field对象,它反映此表示的类或接口的指定公共成员字段 对象。

Field[]

getFields() 

返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段 对象。

Field

getDeclaredField(String name) 

返回一个 Field对象,它反映此表示的类或接口的指定已声明字段 对象。 暴力反射

Field[]

getDeclaredFields() 

返回的数组 Field对象反映此表示的类或接口声明的所有字段 对象。

 

void

set(Object obj, Object value) 

将指定对象参数上的此 Field对象表示的字段设置为指定的新值。

 

解剖构造方法

Constructor<T>

getConstructor(<?>... parameterTypes) 

返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 函数。

Constructor<?>[]

getConstructors() 

返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造 对象。

Constructor<T>

getDeclaredConstructor(<?>... parameterTypes) 

返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 函数。

Constructor<?>[]

getDeclaredConstructors() 

返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组  。

 

T

newInstance(Object... initargs) 

使用此 Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例。

 

解剖成员方法

 

方法

getMethod(String name, 类<?>... parameterTypes) 

返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法 对象。

方法[]

getMethods() 

返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 对象,包括那些由类或接口和那些从超类和超接口继承的声明。

 

Object

invoke(Object obj, Object... args) 

在具有指定参数的 方法对象上调用此 方法对象表示的底层方法。

实例一:

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

public class Test01 {

 

public static void main(String[] args) throws Exception {

/* //在文档里面,查找类的时候直接输入  类,输入Class找不到

Class class1 = Person.class;//获取类的字节码对象的第一种方式  类名.class

Class class2 = new Person().getClass();//获取类的字节码对象的第二种方式  对象名.getClass()

Class class3 = Class.forName("com.xiongluoluo.review.Person");

获取类的字节码对象的第三种方式,使用Class中的静态方法forName,

输入类的全路径,获取类的字节码对象,此方法需要声明异常,但是很常用

Class.forName("全路径")方法获得的类型默认是Class

 

 

System.out.println(class1==class2);//true

System.out.println(class2==class3);//true

//类的字节码文件只会加载一次,存在方法区,所以,都是一样的

 

System.out.println("***************************");

 

//使用类的字节码对象,访问类的成员变量

//Field field1 = class1.getField("name");//普通反射:只能访问public

//由于name字段是私有的,所以这样写会抛出异常

Field field2 = class2.getDeclaredField("name");//暴力反射:可以访问类中所有成员变量

System.out.println(field2);

Field[] fields1 = class1.getFields();//普通反射:只能访问类中所有被public修饰的成员变量

Field[] fields2 = class2.getDeclaredFields();//暴力反射:能访问类中所有成员变量,无论是私有还是非私有的

for(Field field : fields1) {

System.out.println(field);

}

System.out.println("***************************");

for(Field field : fields2) {

System.out.println(field);

}

 

System.out.println("***************************");

 

//使用类的字节码对象,访问类的构造方法

Constructor c1 = class1.getConstructor();//获取无参的构造方法(public修饰的),如果无参构造方法不是public修饰,将会抛出异常

System.out.println(c1);

Constructor c2 = class1.getDeclaredConstructor(String.class,int.class,boolean.class);

//获取有参数的构造方法时,参数要写参数类型的的字节码对象.(获取有参的构造方法,无论构造方法是私有还是非私有,都可以获取)

System.out.println(c2);

System.out.println("***************************");

Constructor[] cons = class1.getConstructors();//获取所有的public修饰的构造方法

for(Constructor c : cons) {

System.out.println(c);

}

System.out.println("***************************");

Constructor[] cons2 = class2.getDeclaredConstructors();//获取所有构造方法

for(Constructor c : cons2) {

System.out.println(c);

}

System.out.println("***************************");

//使用类的字节码对象,访问类的成员方法

Method method1 = class1.getMethod("getName");

Object invoke = method1.invoke(new Person());

System.out.println(invoke);

Method method2 = class2.getDeclaredMethod("setAge", int.class);

System.out.println(method2.invoke(new Person(), 22));

 

Method[] methods1 = class1.getMethods();//与上面的机制有所不同,这个可以获取所有的方法,包括父类

for(Method m : methods1) {

System.out.println(m);

}

System.out.println("***************************");

Method[] methods2 = class2.getDeclaredMethods();//这个只能获取子类中特有的方法

for(Method m : methods2) {

System.out.println(m);

}*/

 

Class class1 = Class.forName("com.xiongluoluo.review.Person");

Person p = (Person)class1.getConstructor().newInstance();

//Constructor con = class1.getConstructor(String.class,int.class,boolean.class);只能访问公有构造方法

 

Constructor con1 = class1.getDeclaredConstructor(String.class,int.class,boolean.class);

System.out.println(con1);

con1.setAccessible(true);//如果构造方法是私有的,新建实例前需要设置访问权限,不然会抛异常

Person p2 = (Person)con1.newInstance("熊落落",22,true);

System.out.println(p2);

}

 

}

 

 

class Person{

private String name;

private int age;

private boolean sex;

public Person() {

super();

// TODO Auto-generated constructor stub

}

private Person(String name, int age, boolean sex) {

super();

this.name = name;

this.age = age;

this.sex = sex;

}

private Person(String name,int age) {

this.name = name;

this.age = age;

}

@Override

public String toString() {

return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";

}

public void run() {

System.out.println("我在跑步ing");

}

public void sleep() {

System.out.println("我在睡觉");

}

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;

}

public boolean isSex() {

return sex;

}

public void setSex(boolean sex) {

this.sex = sex;

}

 

}

实例二:

import java.util.Scanner;

 

//输入Apple,流出苹果汁;输入Orange,流出橘子汁(用反射做)

public class Test02 {

 

public static void main(String[] args) throws Exception {

Scanner sc = new Scanner(System.in);

System.out.println("请输入Apple或者Orange:");

String value = sc.nextLine();

Class c = Class.forName("com.xiongluoluo.review." + value);

Fruit f = (Fruit)c.newInstance();

f.blow();

 

}

 

}

 

 

interface Fruit{

public void blow();

}

 

 

class Apple implements Fruit{

public void blow() {

System.out.println("流出苹果汁");

}

}

 

class Orange implements Fruit{

public void blow() {

System.out.println("流出橘子汁");

}

}

实例三:

import java.io.FileInputStream;

import java.io.InputStream;

import java.util.Enumeration;

import java.util.Properties;

 

public class Test03 {

 

public static void main(String[] args) throws Exception {

Class c = Class.forName("com.xiongluoluo.review.Computer");

Computer com = (Computer)c.newInstance();

com.start();

Properties p = new Properties();

InputStream is = new FileInputStream("config.properties");

p.load(is);

Enumeration<Object> elements = p.elements();

while(elements.hasMoreElements()) {

String element = (String)elements.nextElement();

Class c1 = Class.forName("com.xiongluoluo.review." + element);

Card card = (Card)c1.newInstance();

com.useCard(card);

}

com.close();

 

}

 

}

单元测试:

测试分类:黑盒测试、白盒测试

单元测试、集成测试

import org.junit.After;

import org.junit.Before;

import org.junit.Test;

 

public class Test04 {

//不能单独执行

@Before

public void before() {

System.out.println("测试方法执行前执行");

}

 

//放在主类中,主方法外

//选中方法名,点击右键Run As执行测试方法

@Test

public void run() {

int a = 1;

int b = 3;

System.out.println(a+b);

}

 

//不能单独执行

@After

public void after() {

System.out.println("测试方法执行后执行");

}

}

 

Jar包:

  1. 如何生成jar包

 右键项目-->export-->java-->jar file-->选择文件夹(命名.jar)

  1. 如何使用jar包

 新建lib文件夹,把jar包复制进去,需要build path,就可以使用

  1. 第三方jar包

Github   

Scanner:

Scanner:是一个扫描器,可以扫描指定设备的基本数据类型和字符串。

 

构造方法:

Scanner(File source) 

构造一个新的 Scanner ,产生从指定文件扫描的值。

Scanner(String source) 

构造一个新的 Scanner ,产生从指定字符串扫描的值。

Scanner(InputStream source) 

构造一个新的 Scanner ,产生从指定输入流扫描的值。

常用方法

 nextXxx:获取基本数据类型  分隔格:空格 换行

 没有nextChar(),nextString()这两个方法

 nextLine():获取字符串 分隔符:换行

next():获取字符串  分隔符:空格

空格分隔符和换行分隔符交叉使用

import java.util.Scanner;

 

import com.ujiuye.bean.Student;

 

public class Demo03 {

 

public static void main(String[] args) {

//method01();

//method02_第一种解决方案();

//method02_第二种解决方案();

method02_第三种解决方案();

 

Student s = new Student();

 

}

 

private static void method02_第三种解决方案() {

//都转为字符串,数字通过Integer.parseInt(str)获取

Scanner sc = new Scanner(System.in);

String line = sc.nextLine();

int i = Integer.parseInt(line);

String str = sc.nextLine();

System.out.println(i);

System.out.println(str);

 

}

 

private static void method02_第二种解决方案() {

//定义两个Scanner,上下无联系

Scanner sc = new Scanner(System.in);

int i = sc.nextInt();

System.out.println(i);

sc = new Scanner(System.in);

String str = sc.nextLine();

System.out.println(str);

 

}

 

private static void method02_第一种解决方案() {

Scanner sc = new Scanner(System.in);

//空格  换行  10

int i = sc.nextInt();

System.out.println(i);

sc.nextLine();//返回来的第一个空串,但是不接收这个数据

//回车

String str = sc.nextLine();

System.out.println(str+"...");

 

}

 

private static void method01() {

Scanner sc = new Scanner(System.in);

//空格  换行  10

int i = sc.nextInt();

System.out.println(i);

//回车

String str = sc.nextLine();

System.out.println(str+"...");

}

 

}

建议:不要交叉使用。(我一定不会用的,麻烦)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值