單元測(cè)試:
沒(méi)有單元測(cè)試時(shí)是怎么測(cè)試代碼的?
Junit單元測(cè)試框架
優(yōu)點(diǎn):
單元測(cè)試的具體步驟:
常用注解:
這里我們采用Junit4的版本的注解,這個(gè)版本比較經(jīng)典。
示例代碼:
比如我們有一個(gè)StringUtil類,是我們寫好的一個(gè)類:------也就是等待測(cè)試的類
package com.itheima.d1_junit;
public class StringUtil {
public static void printNumber(String name){
if(name == null){
System.out.println(0);
return; // 停掉方法
}
System.out.println("名字長(zhǎng)度是:" + name.length());
}
/**
* 求字符串的最大索引
*/
public static int getMaxIndex(String data){
if(data == null) {
return -1;
}
return data.length() - 1;
}
}
我們要測(cè)試其中的方法,看看有沒(méi)有問(wèn)題
創(chuàng)建一個(gè)StringUtilTest類來(lái)開(kāi)始進(jìn)行單元測(cè)試:---步驟上面說(shuō)過(guò)了,一共有四步
package com.itheima.d1_junit;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* 測(cè)試類
*/
public class StringUtilTest {
@Before
public void test1(){
System.out.println("---> test1 Before 執(zhí)行了---------");
}
@Test
public void testPrintNumber(){
StringUtil.printNumber("admin");
StringUtil.printNumber(null);//測(cè)試的時(shí)候要全面一點(diǎn)
}
@Test
public void testGetMaxIndex(){
int index1 = StringUtil.getMaxIndex(null);
System.out.println(index1);
int index2 = StringUtil.getMaxIndex("admin");
System.out.println(index2);
//斷言機(jī)制:程序員可以通過(guò)預(yù)測(cè)業(yè)務(wù)方法的結(jié)果。
//4!=index2 --輸出bug
Assert.assertEquals("方法內(nèi)部有bug!", 4, index2);
}
}
測(cè)試的時(shí)候,把鼠標(biāo)光標(biāo)點(diǎn)到某測(cè)試方法中,想要一鍵測(cè)試某個(gè)類中的所有方法,那就把光標(biāo)點(diǎn)到StringUtilTest上,如何想把整個(gè)模塊的測(cè)試類都一鍵測(cè)試,怎么實(shí)現(xiàn)?
點(diǎn)擊Run All Tests即可,非常方便。
反射:
反射學(xué)什么?
學(xué)習(xí)獲取類的信心,操作它們:
反射第一步:
獲取class對(duì)象的三種方法:
代碼演示:
準(zhǔn)備一個(gè)學(xué)生類:
package com.itheima.d2_reflect;
public class Student {
private String name;
private int age;
private char sex;
private double height;
private String hobby;
public Student() {
}
public Student(String name, int age, char sex, double height, String hobby) {
this.name = name;
this.age = age;
this.sex = sex;
this.height = height;
this.hobby = hobby;
}
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 char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
}
獲取該學(xué)生類的class對(duì)象:
?
package com.itheima.d2_reflect;
public class Test1Class {
public static void main(String[] args) throws Exception {
Class c1 = Student.class;
System.out.println(c1.getName()); // 全類名
System.out.println(c1.getSimpleName()); // 簡(jiǎn)名:Student
Class c2 = Class.forName("com.itheima.d2_reflect.Student");
System.out.println(c1 == c2);
Student s = new Student();
Class c3 = s.getClass();
System.out.println(c3 == c2);
//com.itheima.d2_reflect.Student
//Student
//true
//true
}
}
獲取類的構(gòu)造器,并對(duì)其進(jìn)行操作:
獲取類的構(gòu)造器作用:
初始化對(duì)象返回。
代碼演示:
這里準(zhǔn)備一個(gè)Cat類:
?
package com.itheima.d2_reflect;
public class Cat {
public static int a;
public static final String COUNTRY = "中國(guó)";
private String name;
private int age;
private Cat(){
System.out.println("無(wú)參數(shù)構(gòu)造器執(zhí)行了~~");
}
private Cat(String name, int age) {
System.out.println("有參數(shù)構(gòu)造器執(zhí)行了~~");
this.name = name;
this.age = age;
}
private void run(){
System.out.println("??跑的賊快~~");
}
public void eat(){
System.out.println("??愛(ài)吃貓糧~");
}
private String eat(String name){
return "??最愛(ài)吃:" + name;
}
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;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
寫測(cè)試代碼:----講解在注釋中
package com.itheima.d2_reflect;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.util.concurrent.atomic.AtomicInteger;
public class Test2Constructor {
@Test
public void testGetConstructors(){
// 1、反射第一步:必須先得到這個(gè)類的Class對(duì)象
Class c = Cat.class;
// 2、獲取類的全部構(gòu)造器
// Constructor[] constructors = c.getConstructors();
Constructor[] constructors = c.getDeclaredConstructors();
// 3、遍歷數(shù)組中的每個(gè)構(gòu)造器對(duì)象
for (Constructor constructor : constructors) {
System.out.println(constructor.getName() + "--->"
+ constructor.getParameterCount());//名和參數(shù)
}
}
@Test
public void testGetConstructor() throws Exception {
// 1、反射第一步:必須先得到這個(gè)類的Class對(duì)象
Class c = Cat.class;
// 2、獲取類的某個(gè)構(gòu)造器:無(wú)參數(shù)構(gòu)造器
Constructor constructor1 = c.getDeclaredConstructor();
System.out.println(constructor1.getName() + "--->"
+ constructor1.getParameterCount());
constructor1.setAccessible(true); // 禁止檢查訪問(wèn)權(quán)限 因?yàn)槭莗rivate權(quán)限,不加這一行下面2行會(huì)出現(xiàn)異常
Cat cat = (Cat) constructor1.newInstance();//返回Object類型,強(qiáng)轉(zhuǎn)
System.out.println(cat);
// 3、獲取有參數(shù)構(gòu)造器
Constructor constructor2 =
c.getDeclaredConstructor(String.class, int.class);
System.out.println(constructor2.getName() + "--->"
+ constructor2.getParameterCount());
constructor2.setAccessible(true); // 禁止檢查訪問(wèn)權(quán)限
Cat cat2 = (Cat) constructor2.newInstance("叮當(dāng)貓", 3);
System.out.println(cat2);
}
}
獲取類的成員變量:
獲取到成員變量的作用:
賦值,取值。
代碼演示:
這里準(zhǔn)備一個(gè)Cat類:
?
package com.itheima.d2_reflect;
public class Cat {
public static int a;
public static final String COUNTRY = "中國(guó)";
private String name;
private int age;
public Cat(){
System.out.println("無(wú)參數(shù)構(gòu)造器執(zhí)行了~~");
}
private Cat(String name, int age) {
System.out.println("有參數(shù)構(gòu)造器執(zhí)行了~~");
this.name = name;
this.age = age;
}
private void run(){
System.out.println("??跑的賊快~~");
}
public void eat(){
System.out.println("??愛(ài)吃貓糧~");
}
private String eat(String name){
return "??最愛(ài)吃:" + name;
}
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;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
測(cè)試代碼:
?
package com.itheima.d2_reflect;
import org.junit.Test;
import java.lang.reflect.Field;
public class Test3Field {
@Test
public void testGetFields() throws Exception {
// 1、反射第一步:必須是先得到類的Class對(duì)象
Class c = Cat.class;
// 2、獲取類的全部成員變量。
Field[] fields = c.getDeclaredFields();
// 3、遍歷這個(gè)成員變量數(shù)組
for (Field field : fields) {
System.out.println(field.getName() + "---> "+ field.getType());
}
// 4、定位某個(gè)成員變量
Field fName = c.getDeclaredField("name");
System.out.println(fName.getName() + "--->" + fName.getType());
Field fAge = c.getDeclaredField("age");
System.out.println(fAge.getName() + "--->" + fAge.getType());
// 賦值
Cat cat = new Cat();
fName.setAccessible(true); // 禁止訪問(wèn)控制權(quán)限 因?yàn)椋簆rivate String name;
fName.set(cat, "卡菲貓");
System.out.println(cat);
// 取值
String name = (String) fName.get(cat);
System.out.println(name);
}
}
獲取類的成員方法:
獲取類的成員方法作用:
執(zhí)行。
代碼演示:
?
借用------獲取成員變量里面的Cat類
開(kāi)始測(cè)試:
?
package com.itheima.d2_reflect;
import org.junit.Test;
import java.lang.reflect.Method;
public class Test4Method {
@Test
public void testGetMethods() throws Exception {
// 1、反射第一步:先得到Class對(duì)象。
Class c = Cat.class;
// 2、獲取類的全部成員方法。
Method[] methods = c.getDeclaredMethods();
// 3、遍歷這個(gè)數(shù)組中的每個(gè)方法對(duì)象
for (Method method : methods) {
System.out.println(method.getName() + "--->"
+ method.getParameterCount() + "---->"
+ method.getReturnType());
}
// 4、獲取某個(gè)方法對(duì)象
Method run = c.getDeclaredMethod("run"); // 拿run方法,無(wú)參數(shù)的
System.out.println(run.getName() + "--->"
+ run.getParameterCount() + "---->"
+ run.getReturnType());
Method eat = c.getDeclaredMethod("eat", String.class);
System.out.println(eat.getName() + "--->"
+ eat.getParameterCount() + "---->"
+ eat.getReturnType());
Cat cat = new Cat();
run.setAccessible(true); // 禁止檢查訪問(wèn)權(quán)限
Object rs = run.invoke(cat); // 調(diào)用無(wú)參數(shù)的run方法,用cat對(duì)象觸發(fā)調(diào)用的。
System.out.println(rs);//null
eat.setAccessible(true); // 禁止檢查訪問(wèn)權(quán)限
String rs2 = (String) eat.invoke(cat, "魚兒");
System.out.println(rs2);//??最愛(ài)吃:魚兒
}
}
反射的作用:
反射的重要用途:
使用反射做一個(gè)簡(jiǎn)易版的框架
需求:
實(shí)現(xiàn)步驟:
準(zhǔn)備一個(gè)Student類:
?
package com.itheima.d2_reflect;
public class Student {
private String name;
private int age;
private char sex;
private double height;
private String hobby;
public Student() {
}
public Student(String name, int age, char sex, double height, String hobby) {
this.name = name;
this.age = age;
this.sex = sex;
this.height = height;
this.hobby = hobby;
}
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 char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
}
準(zhǔn)備一個(gè)Teacher類:
?
package com.itheima.d2_reflect;
public class Teacher {
private String name;
private double salary;
public Teacher() {
}
public Teacher(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
測(cè)試類如下:
package com.itheima.d2_reflect;
import org.junit.Test;
public class Test5Frame {
@Test
public void save() throws Exception {
Student s1 = new Student("黑馬吳彥祖", 45, '男', 185.3, "藍(lán)球,冰球,閱讀");
Teacher t1 = new Teacher("播妞", 999.9);
// 需求:把任意對(duì)象的字段名和其對(duì)應(yīng)的值等信息,保存到文件中去。
ObjectFrame.saveObject(s1);
ObjectFrame.saveObject(t1);
}
}
還剩一個(gè)框架沒(méi)寫,如下是框架類:
package com.itheima.d2_reflect;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
public class ObjectFrame {
// 目標(biāo):保存任意對(duì)象的字段和其數(shù)據(jù)到文件中去
public static void saveObject(Object obj) throws Exception {
PrintStream ps = new PrintStream(new FileOutputStream("D:\\code\\javasepro\\helloworld-app\\src\\data.txt", true));
// obj是任意對(duì)象,到底有多少個(gè)字段要保存。
Class c = obj.getClass();
String cName = c.getSimpleName();
ps.println("---------------" + cName + "------------------------");
// 2、從這個(gè)類中提取它的全部成員變量
Field[] fields = c.getDeclaredFields();
// 3、遍歷每個(gè)成員變量。
for (Field field : fields) {
// 4、拿到成員變量的名字
String name = field.getName();
// 5、拿到這個(gè)成員變量在對(duì)象中的數(shù)據(jù)。
field.setAccessible(true); // 禁止檢查訪問(wèn)控制
String value = field.get(obj)+""; //(String)強(qiáng)轉(zhuǎn)不可用
ps.println(name + "=" + value);
}
ps.close();
}
}
注意注釋中的細(xì)節(jié)。
測(cè)試結(jié)果圖:-----正常運(yùn)行
注解
自定義注解:
在IDEA中創(chuàng)建注解:----選擇Annotation即可。
這里我們準(zhǔn)備一個(gè)MyTest注解:
?
package com.itheima.d3_annotation;
public @interface MyTest1 {
//public可以不寫
String aaa();
boolean bbb() default true;
String[] ccc();
}
我們準(zhǔn)備一個(gè)MyTest2注解:
package com.itheima.d3_annotation;
public @interface MyTest2 {
String value(); // 特殊屬性
int age() default 23;
}
創(chuàng)建測(cè)試類:---注意注釋
?
package com.itheima.d3_annotation;
@MyTest1(aaa="牛魔王",ccc={"HTML", "Java"})
// @MyTest2(value = "孫悟空")
//@MyTest2("孫悟空") 只有一個(gè)value可以這樣寫
//@MyTest2(value = "孫悟空", age = 1000) 加個(gè)age就不行,age沒(méi)有默認(rèn)值
@MyTest2("孫悟空") //如果age有 默認(rèn)值,又可以這樣寫
public class AnnotationTest1 {
@MyTest1(aaa="鐵扇公主", bbb=false, ccc={"Python", "前端", "Java"})
public void test1(){
}
public static void main(String[] args) {
//執(zhí)行main方法
}
}
我們執(zhí)行main方法后,每個(gè)注解會(huì)生成一個(gè).class文件,這個(gè)文件在哪?
右擊我們的模塊,找到Open ln ->Explorer,點(diǎn)擊它,出現(xiàn)下方圖:
點(diǎn)out文件夾,一直找到我們的包,就能看到.class文件:---只截取一部分
我們要用反編譯軟件編譯它:
下面鏈接是反編譯軟件。
鏈接:https://pan.baidu.com/s/1MhyR5wqQHCwHVU84fHvGsw?pwd=8888?
提取碼:8888
下載完反編譯軟件后,點(diǎn)擊下圖的exe文件:
把MyTest1.class文件拖進(jìn)去就能看到真正的源碼了:
總結(jié):
元注解
定義:
代碼示例:
?
元注解寫法:? ?---元注解是修飾注解的注解。
package com.itheima.d3_annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD}) // 當(dāng)前被修飾的注解只能用在類上,方法上。
@Retention(RetentionPolicy.RUNTIME) // 控制下面的注解一直保留到運(yùn)行時(shí)
public @interface MyTest3 {
}
測(cè)試代碼:
?
package com.itheima.d3_annotation;
@MyTest3
public class AnnotationTest2 {
// @MyTest3 不能用在變量上
private String name;
@MyTest3
public void test(){
}
}
注解的解析
如何解析注解:
解析注解案例
需求:
代碼示例:
MyTest4類:
package com.itheima.d3_annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest4 {
String value();
double aaa() default 100;
String[] bbb();
}
Demo類:
?
package com.itheima.d3_annotation;
@MyTest4(value = "蜘蛛精", aaa=99.5, bbb = {"至尊寶", "黑馬"})
@MyTest3
public class Demo {
@MyTest4(value = "孫悟空", aaa=199.9, bbb = {"紫霞", "牛夫人"})
public void test1(){
}
}
測(cè)試類:
?
package com.itheima.d3_annotation;
import org.junit.Test;
import java.lang.reflect.Method;
import java.util.Arrays;
public class AnnotationTest3 {
@Test
public void parseClass(){
// 1、先得到Class對(duì)象
Class c = Demo.class;
// 2、解析類上的注解
// 判斷類上是否包含了某個(gè)注解
if(c.isAnnotationPresent(MyTest4.class)){
MyTest4 myTest4 =
(MyTest4) c.getDeclaredAnnotation(MyTest4.class);
System.out.println(myTest4.value());
System.out.println(myTest4.aaa());
System.out.println(Arrays.toString(myTest4.bbb()));
}
}
@Test
public void parseMethod() throws Exception {
// 1、先得到Class對(duì)象
Class c = Demo.class;
Method m = c.getDeclaredMethod("test1");
// 2、解析方法上的注解
// 判斷方法對(duì)象上是否包含了某個(gè)注解
if(m.isAnnotationPresent(MyTest4.class)){
MyTest4 myTest4 =
(MyTest4) m.getDeclaredAnnotation(MyTest4.class);
System.out.println(myTest4.value());
System.out.println(myTest4.aaa());
System.out.println(Arrays.toString(myTest4.bbb()));
}
}
}
模擬Junit框架
需求:
代碼示例:
MyTest類:
?
package com.itheima.d3_annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) // 注解只能注解方法。
@Retention(RetentionPolicy.RUNTIME) // 讓當(dāng)前注解可以一直存活著。
public @interface MyTest {
}
開(kāi)始模擬:
package com.itheima.d3_annotation;
import java.lang.reflect.Method;
public class AnnotationTest4 {
// @MyTest
public void test1(){
System.out.println("===test1====");
}
@MyTest
public void test2(){
System.out.println("===test2====");
}
//@MyTest
public void test3(){
System.out.println("===test3====");
}
@MyTest
public void test4(){
System.out.println("===test4====");
}
public static void main(String[] args) throws Exception {
AnnotationTest4 a = new AnnotationTest4();
// 啟動(dòng)程序!
// 1、得到Class對(duì)象
Class c = AnnotationTest4.class;
// 2、提取這個(gè)類中的全部成員方法
Method[] methods = c.getDeclaredMethods();
// 3、遍歷這個(gè)數(shù)組中的每個(gè)方法,看方法上是否存在@MyTest注解,存在
// 觸發(fā)該方法執(zhí)行。
for (Method method : methods) {
if(method.isAnnotationPresent(MyTest.class)){
// 說(shuō)明當(dāng)前方法上是存在@MyTest,觸發(fā)當(dāng)前方法執(zhí)行。
method.invoke(a);
}
}
}
}
模擬結(jié)果: ---完美運(yùn)行
動(dòng)態(tài)代理
程序?yàn)槭裁葱枰??代理長(zhǎng)什么樣?
代理的案例圖:
如何為Java對(duì)象創(chuàng)建一個(gè)代理對(duì)象?
代碼示例:
根據(jù)案例圖
先創(chuàng)建Star接口---當(dāng)作中介公司:
package com.itheima.d4_proxy;
public interface Star {
String sing(String name);
void dance();
}
創(chuàng)建BigStar類:-----明星類
package com.itheima.d4_proxy;
public class BigStar implements Star {
private String name;
public BigStar(String name) {
this.name = name;
}
public String sing(String name){
System.out.println(this.name + "正在唱:" + name);
return "謝謝!謝謝!";
}
public void dance(){
System.out.println(this.name + "正在優(yōu)美的跳舞~~");
}
}
創(chuàng)建代理類:
package com.itheima.d4_proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtil {
public static Star createProxy(BigStar bigStar){
/* newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
參數(shù)1:用于指定一個(gè)類加載器
參數(shù)2:指定生成的代理長(zhǎng)什么樣子,也就是有哪些方法
參數(shù)3:用來(lái)指定生成的代理對(duì)象要干什么事情
*/
// 主程序:Star starProxy = ProxyUtil.createProxy(s);
// starProxy.sing("好日子") starProxy.dance() 去調(diào)用 invoke
Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
new Class[]{Star.class}, new InvocationHandler() {
@Override // 回調(diào)方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 代理對(duì)象要做的事情,會(huì)在這里寫代碼
if(method.getName().equals("sing")){
System.out.println("準(zhǔn)備話筒,收錢20萬(wàn)");
}else if(method.getName().equals("dance")){
System.out.println("準(zhǔn)備場(chǎng)地,收錢1000萬(wàn)");
}
return method.invoke(bigStar, args);
}
});
return starProxy;
}
}
創(chuàng)建測(cè)試類:
?
package com.itheima.d4_proxy;
public class Test {
public static void main(String[] args) {
BigStar s = new BigStar("楊超越");
Star starProxy = ProxyUtil.createProxy(s);
String rs = starProxy.sing("好日子");
System.out.println(rs);
starProxy.dance();
}
}
運(yùn)行結(jié)果圖:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-814307.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-814307.html
到了這里,關(guān)于Java:高級(jí)技術(shù)講解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!