java高级

多线程
    * 多线程概述
        a) 什么是进程?(正在执行的程序,就是一个应用程序在内存中开辟的空间)
        b) 什么是线程?(其实就是进程中的一个控制单元,负责就是程序的执行)
        c) JVM:它自身就是多线程的,因为在程序运行过程中会在堆内存中产生很多的垃圾,就需要被垃圾回收机制进行回收。Main函数代码执行时,也在运行着垃圾回收,所以是同时执行的,这就是两个独立的线程来进行控制的。
        d) 执行垃圾回收的线程,称之为垃圾回收线程.执行main函数的线程,称之为主线程。    
        e) 创建线程的目的:就是让单独一个线程去执行指定的代码(需要多部分代码同时执行)。
        进程和线程的区别:进程是操作系统的概念,线程是应用程序的概念
    * 多线程的特点:
        a) 随机性:发现运行结果每一次都是不一样的,这是因为多线程都获取了CPU的执行权,CPU执行到谁,谁就执行
            明确一点,在某个时刻,只有一个线程在执行,CPU做着快速的切换,看上去是同时运行,我们可以形象的把多线程的的运行行为称为在互相抢夺CPU的执行权,谁抢到谁执行,至于执行多久CPU说了算。
        b) 为什么要覆盖run方法?Thread类用于描述线程,该类定义了一个功能,用于存储线程要运行的代码,该存储代码功能就是run方法,也就是Thread类中的run方法,用于存储线程要运行的代码。
        c) 线程名称:线程都有默认的名称,格式:Thread-编号,该编号从0开始,它可以通过方法来对线程名进行获取,以及修改。
    * 创建多线程方式(两种)
        第一种:
            1. 继承Thread类
            2. 覆盖Thread类中的run方法、在该方法中定义线程要运行的代码
            3. 调用线程对象的start方法,开启线程。Start作用:启动线程,调用run方法。
        第二种:
            1. 定义类实现Runnable接口
            2. 覆盖Runnable接口的run方法,将线程要运行的代码存储到run方法中。
            3. 通过Thread类创建线程对象。
            4. 将实现了Runnable接口的子类对象作为实际参数传入Thread类的构造函数,
            5. 调用Thread类的start方法。
    * Runnable的好处:
        a) Runnbale接口的出现,避免了单继承的局限性。
        b) 将线程运行的代码都单独封装到Runnable接口类型的对象中,这样就实现了线程对象和任务对象的解耦(降低耦合性).
    * 线程运行状态
        NEW             至今尚未启动的线程的状态。 
        RUNNABLE        正在运行线程的线程状态。
        BLOCKED         受阻塞并且正在等待监视器锁的某一线程的线程状态。 
        TIMED_WAITING   具有指定等待时间的某一等待线程的线程状态。 
        WAITING         某一等待线程的线程状态。 
        TERMINATED      已终止线程的线程状态。 
    * Thread
        构造函数
            Thread() 
                分配新的 Thread 对象。
            Thread(Runnable target) 
                分配新的 Thread 对象。 
            Thread(Runnable target, String name) 
                分配新的 Thread 对象。 
        方法
            static Thread currentThread() 
                返回对当前正在执行的线程对象的引用。 
            String getName() 
                返回该线程的名称。 
            Thread.State getState() 
                返回该线程的状态。
            void interrupt() 
                中断线程。 (以抛异常的形式中断sleep,join,wait状态的线程) 
            boolean isDaemon() 
                测试该线程是否为守护线程。
            void join() 
                等待该线程终止。 
            void setDaemon(boolean on) 
                将该线程标记为守护线程或用户线程。 
            void setName(String name) 
                改变线程名称,使之与参数 name 相同。 
            static void sleep(long millis) 
                在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。 
            void start() 
                使该线程开始执行;Java 虚拟机调用该线程的 run 方法。 
            static void yield() 
                暂停当前正在执行的线程对象,并执行其他线程。 
    * 停止线程:
        线程停止最终的目的是终止run方法的运行
        Stop方法已经过时,因为该方法具有不固定的安全性。
        停止非冻结状态的线程:添加标识,改变标识使线程停止,例:if(isStop){return;}
        停止冻结状态的线程:thread1.interrupt()方法,令wait或sleep方法抛出异常,从而退出冻结状态,运行catch块的代码(不是冻结状态则不起作用)
    * 守护线程
        调用setDaemon(true)方法的线程是守护线程,方法需要在开启之前调用,也就是说在start方法之前调用。
        当正在运行的线程都是守护线程时,java虚拟机退出(所有线程自动退出,程序终止)
        守护线程中创建的新线程,也是守护线程
    * 线程安全问题:
        * 原因:多线程同时操作共享数据。
        * 解决方案:同步
            将需要同步的代码封装到了指定同步语句块当中。让一个线程在执行多条操作共享数据的运算过程中其他线程不要参与共享数据的操作。
    * 同步方式:
        * 同步代码块:
            synchronized(对象)
            {
                需要被同步的代码
            }
            使用的锁是任意对象。
        * 同步函数(在方法签名中添加synchronized关键字):
            同步函数使用锁的是固定的this(静态方法是类的class对象)。
        * 注意:
            必须要同步线程操作的共享数据
            要保证锁是唯一的
    * 同步的好处、前提、弊端
        好处:
            解决了线程的安全问题,
            因为当一个线程在操作共同数据时,通过同步锁的机制,使得其他的线程不能去操作共享的数据,
            不管这条操作语句在执行过程中处于什么状态,消亡除外。比如sleep或者wait,都要等到它重新获取了执行权,把执行语句执行完毕后才出去。
            这样的话就保证了其他线程在有线程在操作共享数据的时候不能再操作共享数据。
        前提:
            1、同步中如果只有一个线程在执行,就没有必要去同步、
            2、如果有多个线程同步,必须要保证它们使用的是同一个锁。
        弊端:
            对程序的性能有一些影响,会降低一些效率。
            同步嵌套同步的时候,使用的锁不一样,容易引发死锁



多线程通信
    * 前提
        多个线程在操作同一个资源,线程的任务也是不一样的。
    * 目标
        目标一:一个线程生产,一个线程销售,同时只能生产一个,且必须销售完再生产
        目标二:多个线程生产,多个线程销售,同时只能生产一个,且必须销售完再生产
    * 等待唤醒机制:
        Object中的方法:
            void wait() 
                导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。 
            void notify() 
                唤醒在此对象监视器上等待的单个线程。 
            void notifyAll() 
                唤醒在此对象监视器上等待的所有线程。 
            监视器:就是多线程中的锁。
            注意:以上三个方法必须有锁的支持(被锁对象调用),否则报异常
    * wait和sleep的区别:
        1. sleep是Thread类的静态方法,wait是Object类的非静态方法
        2. sleep指定时间,时间到了,自己就醒了;wait可以指定时间,也可以不用指定时间,由其他线程唤醒
        3. wait方法必须有锁的支持,sleep方法不一定。
        4. 在同步中wait sleep对于执行权和锁的处理不同:
            sleep释放CPU执行权,但是没有释放锁。
            wait释放执行权、释放锁。当被唤醒的时候,重新获取锁,wait必须有锁
    * 线程细节:
        Thread类中的方法:
            1、join方法:执行此方法的线程会优先执行(其它线程会暂停,将cpu执行权交给此线程),执行完毕后其它线程继续运行.
            2、setPriority方法:设置线程运行的优先级,线程类中提供了MAX_PRIORITY MIN_PRIORTY NORM_PRIORTY。(在多核cpu中体现不明显)
            3、yield方法(静态方法):线程的让步,暂停当前正在执行的线程对象,并执行其他线程(在多核cpu中体现不明显)
            4、toString方法;获取线程详细信息,包括线程组、线程名、所属线程。
    * Lock接口和Condition接口
        JDK1.5版本后java.util.concurrent.locks包中提供了lock接口和Condition接口
        Lock 改良 synchronized 方法和语句的使用,Condition 改良 Object 监视器方法的使用。
        Lock 接口的实现允许锁定在不同的作用范围内获取和释放,并允许以任何顺序获取和释放多个锁定
        Condition将线程进行分组,线程切换不用唤醒全部线程,只唤醒对方线程的一个线程即可,提高了效率
        Lock 接口:
            Lock 接口提供了lock()获取锁,unlock()释放锁的操作
            例:
                public void run(){
                    Lock lock = new ReentrantLock();//用reentrantLock创建一个lock对象。
                    try{
                        lock.lock();
                        //要执行的代码
                    }finally{
                        lock.unlock();
                    }
                }
        Condition 接口:
            Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用
            Condition对象的获取方法:lock.newCondition();
            Condition接口中的方法:
                await():等待,让当前线程处于冻结状态
                signal(): 唤醒一个等待线程。
                signalAll():唤醒所有等待线程。
            参见 目标二代码(方式二Lock接口和Condition接口)
    * 代码示例:
        * 目标一:一个线程生产,一个线程销售,同时只能生产一个,且必须销售完再生产
            /*
             生产者与消费者
             */
            class Resouce {
                private String name;
                private int count;
                private boolean flag = false;

                public synchronized void set(String name) {
                    if (flag) {
                        try {
                            this.wait();
                        } catch (Exception e) {
                        }
                    }
                    this.name = name + "---" + count;
                    System.out.println(Thread.currentThread().getName() + "生产者----" + this.name);
                    count++;
                    flag = true;
                    this.notify();
                }

                public synchronized void get() {
                    if (!flag){
                        try {
                            this.wait();
                        } catch (Exception e) {
                        }
                    }
                    System.out.println(Thread.currentThread().getName() + "消费者" + this.name);
                    flag = false;
                    this.notify();
                }
            }

            // 创建生产者类
            class Product implements Runnable {
                private Resouce r;
                Product(Resouce r) {
                    this.r = r;
                }
                public void run() {
                    while (true) {
                        r.set("鼠标");
                    }
                }
            }

            // 创建消费者类
            class Custom implements Runnable {
                private Resouce r;
                Custom(Resouce r) {
                    this.r = r;
                }
                public void run() {
                    while (true) {
                        r.get();
                    }
                }
            }

            class HelloService {
                public static void main(String[] args) throws Exception {
                    Resouce r = new Resouce();
                    Product p = new Product(r);
                    Custom c = new Custom(r);
                    Thread t1 = new Thread(p);// 生产者线程
                    Thread t2 = new Thread(c);// 消费者线程
                    t1.start();
                    t2.start();
                }
            }
        * 目标二:多个线程生产,多个线程销售,同时只能生产一个,且必须销售完再生产
            方式一(object提供的方法):
                /*
                 生产者多个与消费者多个
                 唤醒全部线程是浪费的,能不能实现唤醒对方中的一个线程呢?jdk1.5中的Lock接口可以做到
                 */
                class Resouce {
                    private String name;
                    private int count;
                    private boolean flag = false;

                    public synchronized void set(String name) {
                        while (flag) {
                            try {
                                // 线程在这里倒下,唤醒后,如何继续判断flag标记呢
                                this.wait();
                            } catch (Exception e) {
                            }
                        }
                        this.name = name + "---" + count;
                        System.out.println(Thread.currentThread().getName() + "生产者----" + this.name);
                        count++;
                        flag = true;
                        this.notifyAll();
                    }

                    public synchronized void get() {
                        while (!flag){
                            try {
                                this.wait();
                            } catch (Exception e) {
                            }
                        }
                        System.out.println(Thread.currentThread().getName() + "消费者" + this.name);
                        flag = false;
                        this.notifyAll();
                    }
                }

                // 创建生产者类
                class Product implements Runnable {
                    private Resouce r;
                    Product(Resouce r) {
                        this.r = r;
                    }
                    public void run() {
                        while (true) {
                            r.set("鼠标");
                        }
                    }
                }

                // 创建消费者类
                class Custom implements Runnable {
                    private Resouce r;
                    Custom(Resouce r) {
                        this.r = r;
                    }
                    public void run() {
                        while (true) {
                            r.get();
                        }
                    }
                }

                class HelloService {
                    public static void main(String[] args) throws Exception {
                        Resouce r = new Resouce();
                        Product p = new Product(r);
                        Custom c = new Custom(r);
                        Thread t1 = new Thread(p);// 生产者线程
                        Thread t2 = new Thread(p);// 生产者线程
                        Thread t3 = new Thread(p);// 生产者线程
                        Thread t4 = new Thread(p);// 生产者线程
                        Thread t5 = new Thread(c);// 消费者线程
                        Thread t6 = new Thread(c);// 消费者线程
                        Thread t7 = new Thread(c);// 消费者线程
                        Thread t8 = new Thread(c);// 消费者线程
                        t1.start();
                        t2.start();
                        t3.start();
                        t4.start();
                        t5.start();
                        t6.start();
                        t7.start();
                        t8.start();
                    }
                }
            方式二(Lock接口和Condition接口):
                /*
                 生产者多个与消费者多个
                 使用JDK1.5版本提供的锁Lock接口实现线程的安全问题处理 
                 */
                import java.util.concurrent.locks.*;
                class Resouce {
                    private String name;
                    private int count;
                    private boolean flag = false;
                    // 建立锁的对象
                    private Lock lock = new ReentrantLock();
                    // Condition newCondition() 返回绑定到此 Lock 实例的新 Condition 实例。
                    // 唤醒对方中的一个线程,需要对线程进行分组管理,分成两个组,一个生产组,一个消费组
                    // 利用Condition对象,对线程进行分组管理
                    Condition pro = lock.newCondition();
                    Condition cus = lock.newCondition();

                    // set方法,只有生产线程才会执行
                    public void set(String name) {
                        lock.lock();//获取锁
                        while (flag) {
                            try {
                                pro.await();//生产者等待
                            } catch (Exception e) {
                            }
                        }
                        this.name = name + "---" + count;
                        System.out.println(Thread.currentThread().getName() + "生产者----" + this.name);
                        count++;
                        flag = true;
                        cus.signal();//唤醒消费者
                        lock.unlock();//释放锁
                    }

                    public void get() {
                        lock.lock();//获取锁
                        while (!flag){
                            try {
                                cus.await();//消费者等待
                            } catch (Exception e) {
                            }
                        }
                        System.out.println(Thread.currentThread().getName() + "消费者" + this.name);
                        flag = false;
                        pro.signal();//唤醒生成者
                        lock.unlock();//释放锁
                    }
                }

                // 创建生产者类
                class Product implements Runnable {
                    private Resouce r;
                    Product(Resouce r) {
                        this.r = r;
                    }
                    public void run() {
                        while (true) {
                            r.set("鼠标");
                        }
                    }
                }

                // 创建消费者类
                class Custom implements Runnable {
                    private Resouce r;
                    Custom(Resouce r) {
                        this.r = r;
                    }
                    public void run() {
                        while (true) {
                            r.get();
                        }
                    }
                }

                class HelloService {
                    public static void main(String[] args) throws Exception {
                        Resouce r = new Resouce();
                        Product p = new Product(r);
                        Custom c = new Custom(r);
                        Thread t1 = new Thread(p);// 生产者线程
                        Thread t2 = new Thread(p);// 生产者线程
                        Thread t3 = new Thread(p);// 生产者线程
                        Thread t4 = new Thread(p);// 生产者线程
                        Thread t5 = new Thread(c);// 消费者线程
                        Thread t6 = new Thread(c);// 消费者线程
                        Thread t7 = new Thread(c);// 消费者线程
                        Thread t8 = new Thread(c);// 消费者线程
                        t1.start();
                        t2.start();
                        t3.start();
                        t4.start();
                        t5.start();
                        t6.start();
                        t7.start();
                        t8.start();
                    }
                }



定时器(java.util.Timer)
    * 构造方法:
        Timer() 创建一个新计时器。 
        Timer(boolean isDaemon) 创建一个新计时器,并且作为守护线程运行。 
    * 常用方法:
         void schedule(TimerTask task, Date time) 
            安排在指定的时间执行指定的任务。 
         void schedule(TimerTask task, Date firstTime, long period) 
            安排指定的任务在指定的时间开始进行重复的固定延迟执行。 
         void schedule(TimerTask task, long delay) 
            安排在指定延迟后执行指定的任务。 
         void schedule(TimerTask task, long delay, long period) 
            安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。 
        TimerTask为抽象类,重写其中的run方法即可
        注意:非守护线程的定时器一旦指定程序就不会停止,可使用System.exit(0);退出程序



线程本地变量(ThreadLocal对象)
    * 在当前线程中缓冲一个对象,在同一线程取到的是同一个对象
    * 构造方法:
        ThreadLocal()
    * 常用方法:
        void set(T value)   //存入对象
        T get()             //取出对象
        remove()            //移除对象



final、finally、finalize的区别
    final: 是一个修饰符,可以用来修饰类、方法、变量。修饰类不可以被继承、修饰方法不可以被覆盖,修饰变量时是一个最终变量。
    finally: 异常处理当中一定会被执行的语句,常常用来关闭资源,只有遇到System.exit(0);才不执行
    fianlize: 垃圾回收方法,需要被垃圾回收器调用。



字符串(重点)
    * String类(字符串)
        * 概述:
            String 类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。
        * 特点:
            字符串是常量,它们的值在创建之后不能更改。
            String类 底层操作的是字符数组,以字符形式存放在方法区的常量池中
        * 面试题1:
            String s="abc";
            String s1=new Strng("abc");是否相同?
            第一种,变量直接指向常量池首地址,只有一个对象
            第二种,变量指向的是堆内存中的new String对象,new String对象中存储的是字符串常量池首地址,有两个对象
            s1==s2 : 比较的是内存的地址值。false
            s1.equals(s2) : 比较的是内容。True
        * 面试题2:
            String s1="你好";//在缓冲池创建了一个abcd的字符串。
            String s2="吗";
            String s3="你好吗";
            System.out.println(s3==(s1+s2));//false,原因:两个都是变量,在编译时不能确定值,(s1+s2)在运行时会重新分配内存
            System.out.println(s3==("你好"+"吗"));//true,原因:两个都是常量,在编译时已经确定值,("你好"+"吗")不会重新分配内存
        * 常用构造方法
             String(byte[] bytes, Charset charset) 将字节数组按指定编码转换为字符串
             String(byte[] bytes, int offset, int length, String charsetName) 将字节数组按指定编码转换为字符串
             String(char[] value) 将字符数组转换为字符串
        * 常用操作方法
             char charAt(int index) 
                返回指定索引处的 char 值。 
             boolean contains(CharSequence s) 
                当且仅当此字符串包含指定的 char 值序列时,返回 true。 
             boolean endsWith(String suffix) 
                测试此字符串是否以指定的后缀结束。 
             boolean equals(Object anObject) 
                将此字符串与指定的对象比较。 
             boolean equalsIgnoreCase(String anotherString) 
                将此 String 与另一个 String 比较,不考虑大小写。 
             byte[] getBytes(String charsetName) 
                使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 
             int indexOf(String str) 
                返回指定子字符串在此字符串中第一次出现处的索引。 
             int indexOf(String str, int fromIndex) 
                返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。 
             int lastIndexOf(String str) 
                返回指定子字符串在此字符串中最右边出现处的索引。 
             int lastIndexOf(String str, int fromIndex) 
                返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。 
             int length() 
                返回此字符串的长度。 
             boolean matches(String regex) 
                告知此字符串是否匹配给定的正则表达式。 
             String replace(CharSequence target, CharSequence replacement) 
                使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。 
             String replaceAll(String regex, String replacement) 
                使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。 
             String[] split(String regex) 
                根据给定正则表达式的匹配拆分此字符串。 
             boolean startsWith(String prefix) 
                测试此字符串是否以指定的前缀开始。 
             String substring(int beginIndex) 
                返回一个新的字符串,它是此字符串的一个子字符串。 
             String substring(int beginIndex, int endIndex) 
                返回一个新字符串,它是此字符串的一个子字符串。
             char[] toCharArray() 
                将此字符串转换为一个新的字符数组。 
             String toLowerCase() 
                使用默认语言环境的规则将此 String 中的所有字符都转换为小写。 
             String toUpperCase() 
                使用默认语言环境的规则将此 String 中的所有字符都转换为大写。 
             String trim() 
                返回字符串的副本,忽略前导空白和尾部空白。 
             static String valueOf(Object obj) 
                返回 Object 参数的字符串表示形式。 
        * 字符串和字节数组的相互转换
            字符串-->字节数组(指定编码)
                byte[] getBytes(String charsetName) 使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 
            字节数组-->字符串(指定编码)
                String(byte[] bytes, Charset charset) 将字节数组按指定编码转换为字符串
    * StringBuffer类(字符串缓冲区对象)
        * 概述:
            线程安全的可变字符序列。一个类似于 String 的字符串缓冲区。
        * 特点:
            线程安全
            可存放任何类型的数据,这些数据都会被转换为字符串,再添加或插入到字符串缓冲区中.
            底层是字符数组(缓存区即数组的大小,当容量不足时,内容自动转存到一个更大容量的数组)
            字符缓存区最后一般还是要转换为String使用
        * 常用构造方法:
            new StringBuffer() //构造一个其中不带字符的字符串缓冲区,初始容量为 16 个字符。
            new StringBuffer(String str) //构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。
        * 常用操作方法:
            StringBuffer append(Object obj)
                向缓冲区中追加字符串
            StringBuffer insert(int index,Object obj)
                在指定位置上插入字符串
            StringBuffer delete(int start,int end)
                删除缓冲区中的字符 
            StringBuffer deleteCharAt(int index)
                删除指定位置上的字符
            StringBuffer reverse()
                反转字符串
            void setCharAt(int index, char ch)
                修改指定位置的字符
            其它常用方法:indexOf,lastIndexOf,length,replace,substring,toString
            注意:StringBuffer类对象可通过toString方法转换为String类对象,并使用String类的方法
        * 和数组的区别:
            1、数组是固定长度的,必须先明确数据类型和长度,而容器是任意的,也可是同一种类型,
            2、数组对象只能通过length属性通过角标来操作数组元素,但是容器可以通过各种方法来操作元素。
            3、数组中的元素可以通过角标直接进行访问,而字符串缓冲区元素通常操作后要通过toString变成字符串使用。
    * StringBuilder类(字符串缓冲区对象)
        * 由来:
            JDK1.5版本出现的新特性,可以替代StringBuffer
        * 特点:
            线程不同步、效率高、方法和StringBuffer一模一样
    * 三者的区别:
        * 线程安全问题:
            StringBuffer:线程安全
            StringBuilder:线程不安全
        * 效率问题:
            String str1 = s1 + s2 + s3 + s4 + s5 + ...;
                //这种情况进行大字符串拼接时,StringBuffer要快于String
            String str2 = "a" + "b" + "c" + "d" + ...;
                //这种情况进行大字符串拼接时,Stirng速度要快于StringBuffer的append方法
                //因为相加的字符串都是常量,str2在编译时已经确定值
                //当然,一般不会使用那么多常量,所以进行大字符串拼接时,StringBuffer通常要快于String
            在单线程中,StringBuilder要快于StringBuffer
        * 总结:
            三者的底层都是字符数组,string的字符数组的长度就是内容的长度,而StringBuffer的数组长度每次增长的比较大,起到了缓存的作用,提高了效率
            平常使用String,进行大字符串拼接时,单线程使用StringBuilder,多线程使用StringBuffer
        
        

基本数据类型的包装类(java.lang)
    * 基本类型和对应包装类
        int----Integer
        char---Character
        byte---Byte
        short--Short
        long---Long
        double-Double
        float--Float
        boolean-Boolean
    * 将基本数据类型封装成对象的好处
        包装类的值可为null
        可以在对象中定义更多的功能方法操作该数据
    * 构造方法:
        包装类(对应基本类型 obj)
        包装类(String str)
    * 常用操作
        * 将String转换为包装类(Character类没有相应方法)
            包装类.valueOf(String str);
            包装类.parseXXX(String str);    //XXX为对应基本类型
            构造方法
        * 将包装类转换为String
            对象.toString();
            对象+"";
        * 把基本类型转换为包装类
            构造方法
            包装类.valueOf(对应基本类型 obj);
        * 取出包装类中的基本类型值
            对象.XXXValue();    //XXX为对应基本类型
    * 数字进制转换(Integer类静态方法)
        static String toBinaryString(int i) 将十进制转成二进制
        static String toHexString(int i)    将十进制转成十六进制
        static String toOctalString(int i)  将十进制转成八进制
        static String toString(int i, int radix)    将十进制转换为指定进制
        static int parseInt(String str,int radix)   将字符串按指定进制解析,并转为十进制
    * Character类常用方法
         static boolean isDigit(char ch)
            确定指定字符是否为数字。
         static boolean isLetter(char ch)
            确定指定字符是否为字母。
         static boolean isLetterOrDigit(char ch)
            确定指定字符是否为字母或数字。
         static boolean isLowerCase(char ch)
            确定指定字符是否为小写字母。
         static boolean isSpaceChar(char ch)
            确定指定字符是否为 Unicode 空白字符。
         static boolean isUpperCase(char ch)
            确定指定字符是否为大写字母。
         static boolean isWhitespace(char ch) 
            确定指定字符依据 Java 标准是否为空白字符。
         static char reverseBytes(char ch) 
            返回通过反转指定 char 值中的字节顺序而获得的值。
         static char toLowerCase(char ch) 
            使用取自 UnicodeData 文件的大小写映射信息将字符参数转换为小写。
         static char toUpperCase(char ch) 
            使用取自 UnicodeData 文件的大小写映射信息将字符参数转换为大写。
    * 自动拆箱和自动装箱
        装箱,将基本数据类型包装成对象
        拆箱,将包装类型对象变成基本数据类型
        Jdk1.5版本后对基本数据类型对象包装类进行了升级,可以像操作基本数据类型一样操作基本数据类型对象。
            Integer x = 4;  //自动装箱。
            x  = x + 5;     //自动拆箱。
        反编译上面的代码,得到:
            Integer x = Integer.valueOf(4);
            x = Integer.valueOf(x.intValue() + 5);
    * 注意:在多个int自动装箱中,如果自动装箱的数据在byte范围之内,同样的数据不再单独开辟空间
        Integer i1=new Integer(127);
        Integer i2=new Integer(127);
        Integer i3=127;
        Integer i4=127;
        System.out.println(i1==i2);         //false 
        System.out.println(i1.equals(i2));  //true
        System.out.println(i3==i4);         //127为true,128为false(在多个int自动装箱中,如果自动装箱的数据在byte范围之内,同样的数据不再单独开辟空间)
        System.out.println(i3.equals(i4));  //true
        System.out.println(i1==i3);         //false



Object类(java.lang)
    * 概述
        类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。 
    * 构造方法:
        Object() 
    * 常用方法:
         boolean equals(Object obj) 
            指示其他某个对象是否与此对象“相等”。 Object类实现为比较内存地址,相当于==
         Class<?> getClass() 
            返回此 Object 的运行时类。 
         String toString() 
            返回该对象的字符串表示。
    * 多线程相关方法:
         void wait() 
            在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。 
         void wait(long timeout) 
            在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。 
         void notify() 
            唤醒在此对象监视器上等待的单个线程。 
         void notifyAll() 
            唤醒在此对象监视器上等待的所有线程。
    * 其它方法:
         protected  Object clone() 
            创建并返回此对象的一个副本。 
         protected  void finalize() 
            当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。 
         int hashCode() 
            返回该对象的哈希码值。 



equals 和 == 的区别
    ==比较运算符:
        基本数据类型中,比较的是具体数值
        引用数据类型中,比较的是对象的地址值
    equals方法:
        默认比较对象地址值
        子类可以覆盖此方法,指定属于自己的比较方式



System类(java.lang)
    * 概述
        System 类包含一些有用的类字段和方法。它不能被实例化。 
        在 System 类提供的设施中,
            有标准输入、标准输出和错误输出流;
            对外部定义的属性和环境变量的访问;
            加载文件和库的方法;
            还有快速复制数组的一部分的实用方法。 
    * 常用字段 
        static PrintStream err 
            “标准”错误输出流。 
        static InputStream in 
            “标准”输入流。 
        static PrintStream out 
            “标准”输出流。 
    * 常用方法
        static long currentTimeMillis() 
            返回以毫秒为单位的当前时间。 
        static void exit(int status) 
            终止当前正在运行的 Java 虚拟机。 正常退出参数应为0.非0表示不正常退出
        static void gc() 
            运行垃圾回收器。 
        static Map<String,String> getenv() 
            返回一个不能修改的当前系统环境的字符串映射视图。 
        static String getenv(String name) 
            获得指定的环境变量值。 
        static Properties getProperties() 
            确定当前的系统属性 
        static String getProperty(String key) 
            获取指定键指示的系统属性。 
        static void setErr(PrintStream err) 
            重新分配“标准”错误输出流。 
        static void setIn(InputStream in) 
            重新分配“标准”输入流。 
        static void setOut(PrintStream out) 
            重新分配“标准”输出流。 
        static void setProperties(Properties props) 
            将系统属性设置为 Properties 参数。 
        static String setProperty(String key, String value) 
            设置指定键指示的系统属性。
    * 说明:
        该类可以获取JVM启动时从本地系统取到的属性信息,通过一个getProperites方法就可以获取所有的系统的信息
        getProperties():获取当前系统的属性集。它是Hashtable的一个子类,返回值是没有泛型,里面都是固定好的字符。
        获取当前classPath(兼容java项目和web项目)
            String classPath = System.getProperty("java.class.path").split(";")[0];
        获取路径分隔符(兼容windows,UNIX,Linux)
            String line=System.getProperty("line.separator");



Runtime类(java.lang)
    * 概述:
        每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。
        单例设计的体现
    * 获得实例方式  
        static Runtime getRuntime() 
            返回与当前 Java 应用程序相关的运行时对象。 
    * 常用方法:
         Process exec(String command) 
            在单独的进程中执行指定的字符串命令。
         void exit(int status) 
            通过启动虚拟机的关闭序列,终止当前正在运行的 Java 虚拟机。 
         long freeMemory() 
            返回 Java 虚拟机中的空闲内存量。
         void gc() 
            运行垃圾回收器。 
         long totalMemory() 
            返回 Java 虚拟机中的内存总量。 
    * 例:打开一个进程
        Runtime r=Runtime.getRuntime();
        process p= r.exec("notepad");//打开记事本,process为进程对象
        p.destroy();//杀死子线程 java中只能杀它开启的,不是它开启的杀不了。
        Process p=r.exec("kankan.exe E:\\java0218\\xxx.avi");//它不仅能打开某个应用程序,还可以用这个程序打开它关联的文件



Math类(java.lang)
    * 该类中定义了操作数学运算的方法,都是静态的。
    * 常用字段:
        static double E 
            比任何其他值都更接近 e(即自然对数的底数)的 double 值。 
        static double PI 
            比任何其他值都更接近 pi(即圆的周长与直径之比)的 double 值。 
    * 常用方法:
        static double abs(double a) 
            返回 double 值的绝对值。 
        static double ceil(double a) 
            返回最小的(最接近负无穷大)double 值,该值大于等于参数,并等于某个整数。 
        static double floor(double a) 
            返回最大的(最接近正无穷大)double 值,该值小于等于参数,并等于某个整数。 
        static double max(double a, double b) 
            返回两个 double 值中较大的一个。 
        static double min(double a, double b) 
            返回两个 double 值中较小的一个。 
        static double pow(double a, double b) 
            返回第一个参数的第二个参数次幂的值。 
        static double random() 
            返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。 (随机数)
        static long round(double a) 
            返回最接近参数的 long。 (四舍五入) 
        static double sqrt(double a) 
            返回正确舍入的 double 值的正平方根。 



Random类(java.util)
    * 此类的实例用于生成随机数
    * 常用构造方法:
        Random() 
            创建一个新的随机数生成器。
    * 常用方法:
         boolean nextBoolean() 
            返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 boolean 值。 
         void nextBytes(byte[] bytes) 
            生成随机字节并将其置于用户提供的 byte 数组中。 
         double nextDouble() 
            返回下一个伪随机数,它是取自此随机数生成器序列的、在 0.0 和 1.0 之间均匀分布的 double 值。 
         double nextGaussian() 
            返回下一个伪随机数,它是取自此随机数生成器序列的、呈高斯(“正态”)分布的 double 值,其平均值是 0.0,标准差是 1.0。 
         int nextInt() 
            返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。 
         int nextInt(int n) 
            返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。 



日期对象
    * Date类(java.util)
        * 类 Date 表示特定的瞬间,精确到毫秒。 
            应该使用 Calendar 类实现日期和时间字段之间转换,使用 DateFormat 类来格式化和解析日期字符串。
        * 常用构造方法:
            Date() 
            分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒)。
            Date(long date) 
            分配 Date 对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即 1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。
        * 常用方法:
            boolean after(Date when) 
                测试此日期是否在指定日期之后。 
            boolean before(Date when) 
                测试此日期是否在指定日期之前。 
            int compareTo(Date anotherDate) 
                比较两个日期的顺序。 
            long getTime() 
                返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。 
            void setTime(long time) 
                设置此 Date 对象,以表示 1970 年 1 月 1 日 00:00:00 GMT 以后 time 毫秒的时间点。 
    * SimpleDateFormat类(java.text)
        * 以与语言环境有关的方式来格式化和解析日期的具体类
        * 常用构造方法:
            SimpleDateFormat(String pattern) 
            用给定的模式和默认语言环境的日期格式符号构造 SimpleDateFormat。
        * 常用方法:
             String format(Date date) 
                将一个 Date 格式化为日期/时间字符串。 
             Date parse(String source) 
                从给定字符串的开始解析文本,以生成一个日期。 
             String toPattern() 
                返回描述此日期格式的模式字符串。 
        * 最常用操作示例:
            * 格式化日期格式(Date-->String):
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
            * 从字符串解析日期(String-->Date):
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2014-09-22 20:57:32");
    * Calendar类(java.util)
        * 日历
            Calendar 类是一个抽象类,它为特定瞬间(Date)与一组诸如 YEAR、MONTH、HOUR 等 日历字段之间的转换提供了一些方法
            即 可以方便的获取或操作需要的时间信息,如 获取日期的年,月,日,星期 等
        * 获取方式:
            static Calendar getInstance() 
            使用默认时区和语言环境获得一个日历。 
        * 常用方法:
            * 计算:
                abstract void add(int field, int amount) 
                    根据日历的规则,为给定的日历字段添加或减去指定的时间量。 
                boolean after(Object when) 
                    判断此 Calendar 表示的时间是否在指定 Object 表示的时间之后,返回判断结果。 
                boolean before(Object when) 
                    判断此 Calendar 表示的时间是否在指定 Object 表示的时间之前,返回判断结果。 
                int compareTo(Calendar anotherCalendar) 
                    比较两个 Calendar 对象表示的时间值(从历元至现在的毫秒偏移量)。 
            * 获取:
                int get(int field) 
                    返回给定日历字段的值。 
                int getActualMaximum(int field) 
                    给定此 Calendar 的时间值,返回指定日历字段可能拥有的最大值。 
                int getActualMinimum(int field) 
                    给定此 Calendar 的时间值,返回指定日历字段可能拥有的最小值。 
                Date getTime() 
                    返回一个表示此 Calendar 时间值(从历元至现在的毫秒偏移量)的 Date 对象。 
                long getTimeInMillis() 
                    返回此 Calendar 的时间值,以毫秒为单位。 
            * 设置:
                void set(int field, int value) 
                    将给定的日历字段设置为给定值。 
                void set(int year, int month, int date) 
                    设置日历字段 YEAR、MONTH 和 DAY_OF_MONTH 的值。 
                void set(int year, int month, int date, int hourOfDay, int minute) 
                    设置日历字段 YEAR、MONTH、DAY_OF_MONTH、HOUR_OF_DAY 和 MINUTE 的值。  
                void setTime(Date date) 
                    使用给定的 Date 设置此 Calendar 的时间。 
                void setTimeInMillis(long millis) 
                    用给定的 long 值设置此 Calendar 的当前时间值。 
        * get和set方法的常用字段:
            年月日时分秒毫秒:YEAR, MONTH(get(MONTH)的值为月份-1), DAY_OF_MONTH, HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND
            static int DAY_OF_WEEK 一个星期中的某天。从星期天为第一天,所以一般为 结果-1
            static int DAY_OF_YEAR 当前年中的天数。  
            static int WEEK_OF_YEAR 当前年中的星期数。 
        直接打印对象可显示所有字段的信息.



网络通信
    * 网络通信三要素
        * IP地址:
            网络中设备的标识。(32位二进制数,通过IP地址就可以和那台机器进行通信)
            不易记忆,可用主机名(例:www.baidu.com,会先进行域名解析(去DNS服务器查询),解析为IP地址,再进行通信)
            本地回环地址:127.0.0.1 本地主机名:localhost(代表本机)
            查看本地ip的cmd命令:ipconfig
            测试与指定地址是否连通:ping ip或主机名
            ip地址最后一位为255是某一局域网内的广播地址,向广播地址发送数据,此局域网中每台主机都可以接收到数据(如果对应端口开启),可用来实现群聊功能
        * 端口:
            通常说的端口为协议端口,是不同进程的标识,可确定数据由哪个进程接收
            端口号的范围为0~65535,其中0~1024为系统使用或保留端口
            常见默认端口号  HTTP:80   Tomcat:8080   MSSQL:1433   MySQL:3306   Oracle:1521
        * 传输协议:
            通讯的规则
            * 常见协议:TCP,UDP
            UDP:
                面向无连接,不可靠协议(将数据及源和目的封装到数据包中)
                每个数据报限制在64K以内
                不需要建立连接,速度快
            TCP:
                面向连接,可靠的协议
                大数据传输
                经过三次握手,建立连接,速度很慢
    * InetAddress(java.net)
        * 此类表示互联网协议 (IP) 地址。 
        * 获取方式
            static InetAddress getByName(String host) 
                在给定主机名的情况下确定主机的 IP 地址。
            static InetAddress getLocalHost() 
                返回本地主机。 
        * 常用方法
            String getHostAddress() 
                返回 IP 地址字符串(以文本表现形式)。 
            String getHostName() 
                获取此 IP 地址的主机名。 
            boolean isReachable(int timeout) 
                测试是否可以达到该地址。 
    * 套接字(Socket)
        * 概述:
            Socket又称"套接字",是两台机器之间的通信端点,应用程序通常通过"套接字"向网络发出请求或者应答网络请求
            通信的两端都要有Socket,网络通信其实就是Socket间的通信,数据在两个Socket间通过IO传输
        * 套接字连接过程:
            根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。
            (1)服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
            (2)客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
            (3)连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
    * UDP通信
        * 发送端和接收端都使用DatagramSocket类,数据用DatagramPacket封装
        * DatagramSocket(java.net)
            * 此类表示用来发送和接收数据报包的套接字。
            * 常用构造方法
                DatagramSocket() 
                    构造数据报套接字并将其绑定到本地主机上任何可用的端口。
                DatagramSocket(int port) 
                    创建数据报套接字并将其绑定到本地主机上的指定端口。
                DatagramSocket(int port, InetAddress laddr) 
                    创建数据报套接字,将其绑定到指定的本地地址。
            * 常用方法
                void bind(SocketAddress addr) 
                    将此 DatagramSocket 绑定到特定的地址和端口。 
                void close() 
                    关闭此数据报套接字。 
                int getLocalPort() 
                    返回此套接字绑定的本地主机上的端口号。 
                void receive(DatagramPacket p) 
                    从此套接字接收数据报包。 此方法具有线程阻塞效果
                void send(DatagramPacket p) 
                    从此套接字发送数据报包。 
        * DatagramPacket(java.net)
            * 此类表示数据报包。
            * 常用构造方法
                DatagramPacket(byte[] buf, int length) 
                    构造数据报包,用来接收长度为 length 的数据包。 
                DatagramPacket(byte[] buf, int length, InetAddress address, int port) 
                    构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。 
            * 常用方法:
                InetAddress getAddress() 
                    返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。 
                int getLength() 
                    返回将要发送或接收到的数据的长度。 
        * 例:
            * 接收端:
                DatagramSocket socket = new DatagramSocket(10000);      
                byte[] b = new byte[1024];
                DatagramPacket packet = new DatagramPacket(b, b.length);
                System.out.println("正在接受...");
                socket.receive(packet);
                System.out.println(new String(b,0,packet.getLength()));
                socket.close();
            * 发送端:
                DatagramSocket socket = new DatagramSocket();
                byte[] b = "你好".getBytes();
                DatagramPacket packet = new DatagramPacket(b, b.length,InetAddress.getByName("127.0.0.1"),10000);
                socket.send(packet);
                socket.close();
    * TCP通信
        * 分为客户端(Socket) 和 服务端(ServerSocket).
            客户端必须和服务端建立连接,服务端监听到连接后,创建一个新的Socket(与客户端Socket一样)与客户端的Socket进行通信
            通过IO流传输数据,负责传输的IO流要通过连接对象获取
            关闭资源时关闭Socket即可,不必关闭流
        * Socket(java.net)
            * 此类实现客户端套接字
            * 常用构造方法:
                Socket(String host, int port) 
                    创建一个流套接字并将其连接到指定主机上的指定端口号。
                Socket(String host, int port, InetAddress localAddr, int localPort) 
                    创建一个套接字并将其连接到指定远程主机上的指定远程端口。
            * 常用方法:
                void close() 
                    关闭此套接字。
                InetAddress getInetAddress() 
                    返回套接字连接的地址。 
                InputStream getInputStream() 
                    返回此套接字的输入流。 
                InetAddress getLocalAddress() 
                    获取套接字绑定的本地地址。 
                int getLocalPort() 
                    返回此套接字绑定到的本地端口 。
                OutputStream getOutputStream() 
                    返回此套接字的输出流。 
                int getPort() 
                     返回此套接字连接到的远程端口。 
                void shutdownOutput() 
                    禁用此套接字的输出流。 先刷新输出流,再跟上一个连接终止序列,用来告诉服务器发送完毕
        * ServerSocket(java.net)
            * 此类实现服务器套接字。
                服务器调用accept方法,监听到新连接后创建一个新的Socket(java.net.Socket)与客户端通信
            * 常用构造方法:
                ServerSocket(int port) 
                    创建绑定到特定端口的服务器套接字。
            * 常用方法:
                Socket accept() 
                    侦听并接受到此套接字的连接。 此方法具有线程阻塞效果
                void close() 
                    关闭此套接字。 
        * 例:
            * 服务端:
                ServerSocket serverSocket = new ServerSocket(10000);
                Socket socket = serverSocket.accept();
                InputStream in = socket.getInputStream();
                byte[] b = new byte[1024];
                int len = in.read(b);
                System.out.println(new String(b,0,len));
                socket.close();
                serverSocket.close();
            * 客户端:
                Socket socket = new Socket("localhost",10000);
                OutputStream out = socket.getOutputStream();
                out.write("你好".getBytes());
                socket.close();
        * 注意发送端的刷新和接收端的结束条件
            如聊天时,使用readLine()接收,则发送端发送一句话必须发送一个换行
            如文本文件上传时,使用read或readLine()接收,则发送完毕后要调用shutdownOutput方法告诉服务器接收发送完毕,否则服务器永远接收不到-1或null
        * 上传图片示例(多线程):
            * 服务器:
                public class Test{
                    public static void main(String[]args) throws Exception{
                        ServerSocket serverSocket = new ServerSocket(10000);
                        while(true){
                            Socket socket = serverSocket.accept();      //监听
                            new Thread(new UploadPic(socket)).start();  //开启新线程上传
                        }
                    }
                }

                class UploadPic implements Runnable{
                    private Socket socket;
                    public UploadPic(Socket socket){
                        this.socket = socket;
                    }
                    public void run() {
                        try {
                            //获取源和目的
                            InputStream in = socket.getInputStream();
                            String savePath = "D:/upload";
                            File file = new File(savePath);
                            if(!file.exists()){
                                file.mkdir();
                            }
                            String fileName = System.currentTimeMillis()+new Random().nextInt(10)+".jpg";
                            FileOutputStream out = new FileOutputStream(savePath+"/"+fileName);
                            //读写
                            byte[] b = new byte[1024 * 100];
                            int len = 0;
                            while( (len = in.read(b))!=-1 ){
                                out.write(b, 0, len);
                            }
                            //关闭资源
                            out.close();
                            socket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                            throw new RuntimeException("文件上传失败");
                        }
                    }
                }
            * 客户端:
                public class Test2 {
                    public static void main(String[] args) throws Exception {
                        //建立连接
                        Socket socket = new Socket("localhost",10000);
                        //获取源和目的
                        OutputStream out = socket.getOutputStream();
                        FileInputStream in = new FileInputStream("E:/1.jpg");
                        //读写
                        byte[] b = new byte[1024 * 100];
                        int len = 0;
                        while( (len = in.read(b))!=-1 ){
                            out.write(b, 0, len);
                        }
                        //关闭资源
                        in.close();
                        socket.close();
                    }
                }
        浏览器可以访问计算机开启的服务,并可以接受到Socket发送的信息



反射
    * 概述
        JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
        对于任意一个对象,都能够调用它的任意一个方法和属性;
        这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
    * 功能
        在运行时判断任意一个对象所属的类;
        在运行时构造任意一个类的对象;
        在运行时判断任意一个类所具有的成员变量和方法;
        在运行时调用任意一个对象的方法;
        生成动态代理。
    * 相关类
        * java.lang.Class                   描述字节码文件的类
        * java.lang.reflect.Constructor     描述构造方法的类
        * java.lang.reflect.Method          描述方法的类
        * java.lang.reflect.Field           描述字段的类
        * java.lang.reflect.Type            接口,Class是它唯一的子类
    * java反射的基础是先获取到类的字节码对象(Class对象)
    * Class<T>(java.lang)
        * 概述
            Class 类的实例表示正在运行的 Java 应用程序中的类和接口。(也包括枚举,注解,数组,基本java类型和void关键字)
        * 获取方式
            1. 对象.getClass()
            2. 类名.class   (基本类型也可以使用)
            3. Class.forName(类的全限定名称);
        * 常用方法:
            * 获取父类或父接口:
                Type[] getGenericInterfaces() 
                        返回表示某些接口的 Type,这些接口由此对象所表示的类或接口直接实现。 
                Type getGenericSuperclass() 
                        返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type。 
                Class[] getInterfaces() 
                        确定此对象所表示的类或接口实现的接口。 
                Class<? super T> getSuperclass() 
                        返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。 
            * 获取构造方法:
                Constructor<T> getConstructor(Class... parameterTypes) 
                        返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
                Constructor[] getConstructors() 
                        返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。 
                Constructor<T> getDeclaredConstructor(Class... parameterTypes) 
                        返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。 
                Constructor[] getDeclaredConstructors() 
                        返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。 
            * 获取方法:
                Method getDeclaredMethod(String name, Class... parameterTypes) 
                        返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 
                Method[] getDeclaredMethods() 
                        返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 
                Method getMethod(String name, Class... parameterTypes) 
                        返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 
                Method[] getMethods() 
                        返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。 
            * 获取字段:
                Field getDeclaredField(String name) 
                        返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 
                Field[] getDeclaredFields() 
                        返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段,包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。 
                Field getField(String name) 
                        返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 
                Field[] getFields() 
                        返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。 
            * 获取注解
                <A extends Annotation> A getAnnotation(Class<A> annotationClass) 
                        如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。 
                Annotation[] getAnnotations() 
                        返回此元素上存在的所有注释。 
                Annotation[] getDeclaredAnnotations() 
                        返回直接存在于此元素上的所有注释。 
            * 其它:
                T cast(Object obj) 
                        将一个对象强制转换成此 Class 对象所表示的类或接口。
                ClassLoader getClassLoader() 
                        返回该类的类加载器。 
                String getName() 
                        以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。 
                String getSimpleName() 
                        返回源代码中给出的基础类的简称。 
                URL getResource(String name) 
                        查找带有给定名称的资源。 
                InputStream getResourceAsStream(String name) 
                        查找具有给定名称的资源。 
                TypeVariable<Class<T>>[] getTypeParameters() 
                        按声明顺序返回 TypeVariable 对象的一个数组,这些对象表示用此 GenericDeclaration 对象所表示的常规声明来声明的类型变量。 
                T newInstance() 
                        创建此 Class 对象所表示的类的一个新实例。 只能调用无参构造方法
                Class<?> getDeclaringClass() 
                        如果此 Class 对象所表示的类或接口是另一个类的成员,则返回的 Class 对象表示该对象的声明类。 
            还有进行一些判断的方法,如class对象是否表示一个接口.
        * 注意: 
            字节码对象在内存中时唯一的
            当获取到私有的方法时,不能执行,可先设置 对象.setAccessible(true); 取消java的访问权限检查
            反射可打破单例模式
            利用反射调用集合的add方法,可以向有泛型的集合存入不合法的数据
    * Constructor<T>(java.lang.reflect)
        * 概述
            Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。可以调用构造方法
        * 常用方法:
            Class<T> getDeclaringClass() 
                    返回 Class 对象,该对象表示声明由此 Constructor 对象表示的构造方法的类。 
            Type[] getGenericParameterTypes() 
                    按照声明顺序返回一组 Type 对象,这些对象表示此 Constructor 对象所表示的方法的形参类型。 
            Class<?>[] getParameterTypes() 
                    按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法的形参类型。 
            T newInstance(Object... initargs) 
                    使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。 
    * Method(java.lang.reflect)
        * 概述
            Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 可以调用方法法
        * 常用方法:
            Class<?> getDeclaringClass() 
                    返回表示声明由此 Method 对象表示的方法的类或接口的 Class 对象。 
            Type[] getGenericParameterTypes() 
                    按照声明顺序返回 Type 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型的。 
            Type getGenericReturnType() 
                    返回表示由此 Method 对象所表示方法的正式返回类型的 Type 对象。 
            String getName() 
                    以 String 形式返回此 Method 对象表示的方法名称。 
            Class<?>[] getParameterTypes() 
                    按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。 
            Class<?> getReturnType() 
                    返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。 
            Object invoke(Object obj, Object... args) 
                    对带有指定参数的指定对象调用由此 Method 对象表示的基础方法。 
        还有一些获取注解的方法
    * Field(java.lang.reflect)
        * 概述
            Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。 可以为字段赋值
        * 常用方法:
            Object get(Object obj) 
                    返回指定对象上此 Field 表示的字段的值。 
            Class<?> getDeclaringClass() 
                    返回表示类或接口的 Class 对象,该类或接口声明由此 Field 对象表示的字段。 
            Class<?> getType() 
                    返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。 
            void set(Object obj, Object value) 
                    将指定对象变量上此 Field 对象表示的字段设置为指定的新值。 
        还有一些获取注解的方法
    * 使用反射创建对象的方式(两种):
        1. Class类 的 newInstance 方法,只能调用类的无参构造方法
        2. 通过Class对象获取构造方法,调用Constructor类的newInstance方法.
    * 取消java的访问权限检查:
        当获取到私有的方法时,不能执行,可先设置 对象.setAccessible(true); 
    * 泛型转换(通过子类对象获得父类类型参数变量的运行时实际类型的class对象)
        //获得带泛型信息的父类type对象
        ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
        //获得第一个泛型参数的运行时实际类型的class对象
        Class clazz = (Class) type.getActualTypeArguments()[0];
    * 小练习
        使用反射,获取一个类的某个构造方法,并运行
        使用反射,获取一个类的某个成员方法,并运行
        使用反射,获取一个类的某个成员变量,并为指定对象填充值
    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值