概述:註解能夠加強咱們的java代碼,同時利用反射技術能夠擴充實現不少功能。它們被普遍應用於三大框架底層。傳統咱們經過xml文本文件聲明方式,而如今最主流的開發都是基於註解方式,代碼量少,框架能夠根據註解去自動生成不少代碼,從而減小代碼量,程序更易讀。例如最火爆的SpringBoot就徹底基於註解技術實現。css
分類:
一、JDK自帶註解
二、元註解
三、自定義註解java
JDK註解:
JDK註解的註解,就5個:
一、@Override
二、@Deprecated標記就代表這個方法已通過時了,但我就要用,別提示我過時
三、@SuppressWarnings(「deprecation」) 忽略警告
四、@SafeVarargs jdk1.7出現,堆污染,不經常使用
五、@FunctionallInterface jdk1.8出現,配合函數式編程拉姆達表達式,不經常使用編程
元註解:
描述註解的註解,就5個:
一、@Target 註解用在哪裏:類上、方法上、屬性上數組
ElementType.FIELD 應用於字段或屬性 ElementType.METHOD 應用於方法級 ElementType.TYPE 應用於類的元素
二、@Retention 註解的生命週期:源文件中、class文件中、運行中服務器
RetentionPolicy.RUNTIME 在運行時有效
三、@Inherited 容許子註解繼承
四、@Documented 生成javadoc時會包含註解,不經常使用
五、@Repeatable註解爲可重複類型註解,能夠在同一個地方屢次使用,不經常使用框架
自定義註解:socket
//一,自定義註解:@interface 註解名 //描述註解能夠出現的位置--多個位置上用 @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.SOURCE)//描述註解的生命週期 @interface Test{ //1,給註解添加功能--屬性--語法特殊 String local()default "";//3,給屬性設置默認值,方便直接使用@Test String value();//5,特殊的屬性value } //二,使用註解:@Test //@Test(local="class")//2,當Test註解添加了屬性時,須要給屬性賦值 class taotao{ String name; // @Test//4,因爲屬性設置好了默認值,用時就簡單了 // @Test("123")//6,因爲value屬性比較特殊,能夠簡寫,賦值時省略掉value= @Test(local = "method",value="")//7,給多個屬性賦值時,不能省略value= public void show(){ System.out.println("show()..."); } }
概述:
Reflection(反射) 是 Java 程序開發語言的特徵之一,它容許運行中的 Java 程序對自身進行檢查,或者說「自審「,也有稱做「自省」。反射很是強大,它甚至能直接操做程序的私有屬性。咱們前面學習都有一個概念,private的只能類內部訪問,外部是不行的,但這個規定被反射赤裸裸的打破了。ide
反射就像一面鏡子,它能夠在運行時獲取一個類的全部信息,能夠獲取到任何定義的信息(包括成員變量,成員方法,構造器等),而且能夠操縱類的字段、方法、構造器等部分。函數式編程
Class.forName(「類的全路徑」); 類名.class 對象.getClass();
測試:函數
//方式1: Class.forName("類的全路徑"); Class clazz = Class.forName("java.lang.String"); //方式2: 類名.class Class clazz2 = String.class; //方式3: 對象.getClass(); Class clazz3 = new String().getClass();
測試:
public static void main(String[] args) throws Exception { // method();//獲取Class對象 // method2();//獲取構造方法 // method3();//獲取成員方法 // method4();//獲取成員變量 // method5();//經過反射建立對象 } public static void method5() throws Exception { //1,獲取Class對象 Class<Test2_Student> a = Test2_Student.class; //2,調用實例化方法 -- 也要觸發構造方法,並且觸發的是無參構造 //java.lang.InstantiationException沒有無參構造報異常 Test2_Student as = a.newInstance(); System.out.println("as="+as); //重寫toString()前:as=day18.Test2_Student@15db9742 //重寫toString()後:as=Test2_Student [name=null, age=0, score=0.0] //怎麼觸發含參構造--匹配構造方法裏 參數列表 Constructor<Test2_Student> ass = a.getConstructor(String.class);//指定 //X是建立對象時距離的參數 Test2_Student ass2 = ass.newInstance("jack"); System.out.println("ass2="+ass2); //建立2個參數的構造方法 Constructor<Test2_Student> bss = a.getConstructor(String.class,int.class,double.class); Test2_Student bsss = bss.newInstance("taotao",20,20.1); System.out.println("bsss="+bsss); } //獲取成員變量 public static void method4() { //1,獲取Class對象 Class a = Test2_Student.class; //2,獲取全部的成員變量--只能獲取到public修飾的變量 Field[] as = a.getFields(); //3,遍歷數組,獲得每一個變量ass for(Field ass:as) { //4,獲取變量名 System.out.println(ass.getName()); //5,獲取變量類型 System.out.println(ass.getType().getName()); } } //獲取成員方法 public static void method3() { //1,獲取Class對象 Class<Test2_Student> a = Test2_Student.class; //2,獲取全部成員方法們 --包括本身的和父類的 Method[] as = a.getMethods(); //3,遍歷數組,獲得每一個方法ass for(Method ass:as) { //4,獲取方法名 System.out.println(ass.getName()); //5,獲取方法的參數的類型 Class[] asss = ass.getParameterTypes(); System.out.println(Arrays.toString(asss)); } } //獲取構造方法 public static void method2() { //1,獲取Class對象 --封裝了.class文件裏的全部數據 Class c1 = Test2_Student.class; //2,調用方法 // --得到全部公開的構造方法,並存入數組 Constructor[] cs = c1.getConstructors(); //3,獲取每一個構造方法 for(Constructor css:cs) { //4,獲取構造方法的名字 System.out.println(css.getName()); //5,獲取構造方法的參數 Class[] css1=css.getParameterTypes(); System.out.println(Arrays.toString(css1)); } } //獲取Class對象 public static void method() throws ClassNotFoundException { // Class.forName(「類的全路徑」); // 類名.class // 對象.getClass(); Class c = Class.forName("test.reflect.Test3_Reflect2"); Class c1 = Test3_Reflect2.class; Class c2 = new Test3_Reflect2().getClass(); }
基本API:
public static void main(String[] args) throws Exception { // method();//暴力反射成員方法們 // method2();//暴力反射成員變量 public static void method2() throws Exception { Class<Person> a = Person.class; Field[] as = a.getDeclaredFields(); for(Field ass:as) { System.out.println(ass.getName()); System.out.println(ass.getType().getName()); } //獲取指定的變量 Field f = a.getDeclaredField("score"); f.setAccessible(true); Object obj = a.newInstance(); //設置值--set(1,2)--1是指對象名稱,2是要設置的具體值 f.set(obj, 20.0); //獲取值--get(1)--1是指對象名稱 System.out.println(f.get(obj)); } public static void method() throws Exception{ //1,獲取Class對象 Class<Person> a = Person.class; //2,調用方法暴力反射 Method[] as = a.getDeclaredMethods(); //3,遍歷數組,獲得每一個方法ass for(Method ass:as) { //4,獲取方法名稱 System.out.println(ass.getName()); //5,獲取方法的參數的類型 Class<?>[] asss = ass.getParameterTypes(); System.out.println(Arrays.toString(asss)); } //暴力反射 某個方法 //getDeclaredMethod(1,2)--獲取指定的方法 //--1是指方法名--2是指方法須要的參數類型的Class對象 Method m = a.getDeclaredMethod("game", String.class); Method m1 = a.getDeclaredMethod("eat"); //暴力反射:除了用對API,另外還須要開啓訪問權限 m.setAccessible(true); //執行方法--invoke(1,2)--1是指對象名稱--2是方法須要傳入的參數 Object obj = a.newInstance(); m1.invoke(obj, null); // m.invoke(obj, "張三"); }
概述:
若是一個類存在的意義就是爲指定的另外一個類,能夠把這個類放入另外一個類的內部。就是把類定義在類的內部的狀況就能夠造成內部類的形式。
A類中又定義了B類,B類就是內部類。B類能夠當作A類的一個成員看待。
特色:
一、 內部類能夠直接訪問外部類中的成員,包括私有成員
二、 外部類要訪問內部類的成員,必需要創建內部類的對象
三、 在成員位置的內部類是成員內部類
四、 在局部位置的內部類是局部內部類
//測試 內部類 public class Test1_Inner { public static void main(String[] args) { //建立內部類的對象的語法:外部類對象.內部類對象 Outer.Inner in = new Outer().new Inner(); in.in(); System.out.println(in.age); } } //成員內部類 class Outer{//外部類 String name = "jack"; public void out() { //3,外部類 訪問內部類的 成員--不能夠直接用,須要建立內部類對象 new Inner().in(); System.out.println("out()..."); } //1,內部類--能夠看作是外部類的一個特殊成員,和其餘成員是同級關係 class Inner{ int age = 20; public void in() { //2,內部類 能夠直接 訪問外部類 的成員--能夠 System.out.println(name); System.out.println("in()..."); } } }
package cn.tedu.inner; //測試內部類被private修飾 public class Test5_InnerClass2 { public static void main(String[] args) { //建立內部類對象,並執行show() // Outer2.Inner2 oi = new Outer2().new Inner2();//報錯,Inner2已經被private了 //3,測試被private的內部類的資源可否執行! new Outer2().test(); } } class Outer2{ //2,若是想要訪問private的內部類,能夠訪問外部類提供的對應方法 public void test() { //訪問內部類方法 new Inner2().show(); } //位置在類裏方法外--成員內部類 //1,內部類能夠被private修飾,可是外界沒法直接建立對象了! private class Inner2{ public void show() { System.out.println("Inner2.show()"); } } }
package cn.tedu.inner; //測試內部類被static修飾 public class Test6_InnerClass3 { public static void main(String[] args) { // 建立內部類對象測試show() // Outer3.Inner3 oi = new Outer3().new Inner3();//報錯,緣由是Inner3是靜態的內部類 Outer3.Inner3 oi = new Outer3.Inner3();//Outer3.Inner3經過類名.調用類中的靜態資源 oi.show(); Outer3.Inner3.show2();//調用靜態內部類裏的靜態方法 } } class Outer3{ //1,內部類被static修飾--隨着類的加載而加載,會形成內存資源浪費,並不經常使用! static class Inner3{ public void show() { System.out.println("Inner3.show()"); } static public void show2() { System.out.println("Inner3.show2()"); } } }
//測試 匿名內部類 //總結: //接口能夠直接new對象,要配合匿名內部類使用(在內部類裏重寫了方法 public class Test2_Inner { public static void main(String[] args) { //優化方案:直接new接口,要配合匿名內部類使用(在內部類裏重寫了方法)--佔內存少,不用實現類 Inner in = new Inner() { @Override public void save() { System.out.println("數據保存成功"); } @Override public void delete(int id) { System.out.println("數據刪除成功,id是:"+id); } }; // }.save();//調用指定方法 // }.delete(5);//注意:調用指定方法--匿名對象一次只執行一個任務,只能2選1 in.save(); in.delete(10); } } interface Inner{ //簡寫形式 void save(); void delete(int id); }
建立對象:
ServerSocket(int port) 建立綁定到特定端口的服務器套接字。
經常使用方法:
Socket accept() 偵聽並接受到此套接字的鏈接。 void close() 關閉此套接字。
測試:
//socket通訊的服務器端 public class Test1_Server { public static void main(String[] args) throws IOException { //1,開始服務器--端口號0~65535 //在指定的8887端口號處,等待客戶端的鏈接 ServerSocket server = new ServerSocket(8887); System.out.println("服務器已開啓。。。"); //2,接收客戶端鏈接請求,並創建通訊通道Socket Socket accept = server.accept(); System.out.println("接收一個客戶端的請求。。"); //3,讀取客戶端發來的數據 InputStream in = accept.getInputStream(); //讀到的數據默認是int,轉成字符類型 for(int i = 0;i<5;i++) { char b = (char)in.read(); System.out.print(b); } //4,服務器發送數據 OutputStream out = accept.getOutputStream(); String output = new Scanner(System.in).nextLine(); out.write(output.getBytes()); System.out.println("發送成功"); // } }
建立對象:
Socket(String host, int port) 建立一個流套接字並將其鏈接到指定主機上的指定端口號。
經常使用方法:
InputStream getInputStream() 返回此套接字的輸入流。 OutputStream getOutputStream() 返回此套接字的輸出流。
測試:
//socket通訊的客戶端 public class Test2_Client { static Socket socket =null; public static void main(String[] args) throws IOException { method2();//讀取 method();//寫出 //1,鏈接指定的服務器 //本機ip--127.0.0.1 //實際工做中,要寫服務器的真是ip socket = new Socket("172.199.26.30",8888); System.out.println("客戶端與服務器鏈接成功"); } private static void method2() throws IOException { //3,讀取服務器的數據 InputStream in = socket.getInputStream(); for(int i = 0;i<5;i++) { char b = (char)in.read(); System.out.print(b); } } private static void method() throws IOException { //2,給服務器寫出數據 OutputStream out = socket.getOutputStream(); System.out.println("請輸入發給服務器的數據"); String input = new Scanner(System.in).nextLine(); out.write(input.getBytes()); System.out.println("發送成功"); out.flush(); } }
//服務器端 //讀一行:BufferedReader()--readline() //寫一行:PrintWrite()--println() public class Test3_BufferedReader { public static void main(String[] args) throws IOException { //1,開啓服務器,開放端口 ServerSocket server = new ServerSocket(8886); System.out.println("服務器已開啓"); //2,接收客戶端請求,創建鏈接通道Socket Socket accept = server.accept(); System.out.println("Sosket通道已創建"); // rwmethod();//邊讀邊寫 } public static void rwmethod() throws IOException { //1,建立讀取對象 BufferedReader br = new BufferedReader(new FileReader("./a.txt")); PrintWriter pw = new PrintWriter(new FileWriter("./b.txt")); String line =""; while((line = br.readLine())!=null) {//只要有數據,就一直讀,沒數據就返回null pw.println(line); } br.close(); pw.close(); } /** * 用來寫一行:PW * @param path 要把文檔寫在那個文件裏去 * @param date 寫的內容 * @throws IOException */ public static void writeline(String path,String date) throws IOException { //1,建立對象 PrintWriter pw = new PrintWriter(new FileWriter(path)); //2,寫出一行數據 pw.println(date); //3,釋放資源 pw.close(); } /** * 用來讀一行 * @throws IOException */ public static void readline(String path) throws IOException { //讀一行:BufferedReader BufferedReader br = new BufferedReader(new FileReader(path)); //讀不到數據時,readline()返回null // String line = br.readLine(); String line ="";//建立變量,記錄讀取到的一行數據 while(line !=null) {//只要有數據,就一直讀,沒數據就返回null line = br.readLine();//一行一行讀取數據 System.out.println("line="+line); } br.close(); } }
//客戶端 public class Test3_BufferedSocket { public static void main(String[] args) throws IOException { //1,鏈接指定的服務器--輸入服務器IP地址和端口號 //本機ip--127.0.0.1 Socket socket = new Socket("127.0.0.1",8886); System.out.println("客戶端鏈接成功"); Test3_BufferedReader.writeline("./b.txt","over"); Test3_BufferedReader.readline("./a.txt"); } }
JDK1.5-- 可變長參數(Varargs)method(int a,int...b)
JDK1.7--try--with--resources:自動關閉流
JDK1.8--Lambda表達式
使用Lambda語法來代替 匿名內部類,代碼不只簡潔,並且還可讀 語法:(參數列表) -> {方法體} --接口能夠存在普通方法,可是須要用default/static修飾。