JAVASE-註解+反射+內部類+socket+JDK新特性

1註解

概述:註解能夠加強咱們的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()...");
  }
}

2反射

概述:
Reflection(反射) 是 Java 程序開發語言的特徵之一,它容許運行中的 Java 程序對自身進行檢查,或者說「自審「,也有稱做「自省」。反射很是強大,它甚至能直接操做程序的私有屬性。咱們前面學習都有一個概念,private的只能類內部訪問,外部是不行的,但這個規定被反射赤裸裸的打破了。ide

反射就像一面鏡子,它能夠在運行時獲取一個類的全部信息,能夠獲取到任何定義的信息(包括成員變量,成員方法,構造器等),而且能夠操縱類的字段、方法、構造器等部分。函數式編程

2.1建立對象

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();

2.2經常使用方法

image.png
測試:

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();
    }

2.3暴力反射

基本API:
image.png

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, "張三");
    }

3內部類

概述:
若是一個類存在的意義就是爲指定的另外一個類,能夠把這個類放入另外一個類的內部。就是把類定義在類的內部的狀況就能夠造成內部類的形式。
A類中又定義了B類,B類就是內部類。B類能夠當作A類的一個成員看待。

特色:
一、 內部類能夠直接訪問外部類中的成員,包括私有成員
二、 外部類要訪問內部類的成員,必需要創建內部類的對象
三、 在成員位置的內部類是成員內部類
四、 在局部位置的內部類是局部內部類

3.1成員內部類

//測試 內部類
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()...");
        }
    }
}
被private修飾
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()");
        }
    }
}
被static修飾
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()");
        }
    }
}

3.2 匿名內部類

//測試 匿名內部類
//總結:
//接口能夠直接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);
}

4socket

4.1ServerSocket服務器端

建立對象:

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("發送成功");
        //
        
    }

}

4.2socket客戶端

建立對象:

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();
    }

}

4.3BufferedReader

//服務器端
//讀一行: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();
    }
}

4.4BufferedSocket

//客戶端
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");    
    }

}

5JDK新特性

JDK1.5-- 可變長參數(Varargs)method(int a,int...b)
JDK1.7--try--with--resources:自動關閉流
JDK1.8--Lambda表達式

使用Lambda語法來代替 匿名內部類,代碼不只簡潔,並且還可讀
語法:(參數列表) -> {方法體}
  --接口能夠存在普通方法,可是須要用default/static修飾。
相關文章
相關標籤/搜索