黑马程序员技术交流社区

标题: [成都校区] [打印本页]

作者: Nevada    时间: 2018-12-13 02:06
标题: [成都校区]
Object类
toString   重写后可以直接打印对象
equals     重写后比较两个对象的内容

ClassCastException : 类型转换异常;
-------------------------------------------------
Objects类  public  static boolean equals( Object a, Object b ){...}   Objects.equals( Object a, Object b );

null 不能调方法,否则会抛出空指针异常;
--------------------------------------------------
Date类
精确到毫秒,1000毫秒=1秒;
System.currentTimeMillis()  获取当前系统时间(毫秒)
Date 导包 util

Date类的成员方法: public long getTime() 把日期转换为毫秒   date.getTime()
把毫秒转成时间 new Date(毫秒)
把时间转成毫秒 date.getTime  返回long类型的毫秒

获取当前系统时间
Date date = new Date();
Syestem.out.printlu(date);
--------------------------------------------------------
DateFormat抽象(父)类&SimpleDateFormat(子)类
DateFormat 成员方法:String format(Date date)
                   Date parse(String source)
public SimpleDateFormat(String pattern)
String pattern :指定的模式
y           年
M         月
d          日
H         时
m         分
s         秒
SimpleDateFormat  sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
Date date = new Date();
SimpleDateFormat的对象.format(date)  把日期对象转成指定格式的字符串  

Date date=SimpleDateFormat的对象.parse("字符串");    把符合模式的 字符串解析成Date日期
ParseException解析异常  用throws,或者try ... catch 处理这个异常
------------------------------------------------------------------------------
Calendar类
Calendar c =Calendar.getInstance();  // 多态

public int get()
public void set()
public abstract void add()
public Date getTime()

int year = c.get(Calendar.YEAR)     // 获取年份
c.set(Calendar.YEAR,9999)              // 设置年为9999年
c.add(Calendar.YEAR,2)          // 年份增加2年
c.add(Calendar.MOUTH,-3)        // 月份减少3月
-----------------------------------------------------------------
System类
System.currentTimeMillis()  测试程序效率
System.arraycopy(object src,int srcPos,object dest , int destPos, int length)
------------------------------------------------------------------
StringBuilder类
在内存中始终是一个 数组,占用空间少,拼接效率高;
构造方法: public StringBuilder()
         public StringBuilder(String str)
成员方法: public StringBuilder append(...)       使用append方法无需接收返回值
                StringBuilder sb = new StringBuilder();
                StringBuilder sb1=sb.append("abc").append("def")
         public String toString()
链式编程:方法的返回值是一个对象,可以根据对象继续调用方法

将String 变成 StringBuilder :
        StringBuilder sb = new StringBuilder (str);
将StringBuilder 变成 String:
        String s = sb.toString();
-------------------------------------------------------------------------
包装类
装箱:
        构造方法:
                Integer (int value)
        Integer(String s)
        静态方法:
        static Integer valueOf(int i)
        static Integer valueOf(String s)

拆箱:
        成员方法:
        int  intValue()以int类型 返回Integer 的值

自动装箱:
        Integer in = 1;
自动拆箱:
        in = in + 2;
------------------------------------------------------------------------
基本类型与字符串之间的转换

基本类型-->字符串:
        1.基本数据类型的值+“”;
        2.包装类的静态方法:
                static String toString(int i)
        3.使用String类中的静态方法:
                static String valueOf(int i)

字符串-->基本类型:
        1.public?static?int?parseInt(String?s) :用包装类将字符串参数转换为对应的int基本类型。
                int i=Integer.parseInt("100")

-128~127之间的数字存在常量池中,同一个数字,地址值相同,其余范围数字在堆内存中,地址值不同;

Collection接口
集合储存的都是对象。
共性方法:
1.public boolean add(E e)           返回值不用接收,没有意义;
2.public boolean remove(E e)        删除存在的元素,返回true,删除不存在的元素,返回false;
集合中相同的元素,只会删除第一个;
3.public boolean contains(E e)        判断集合中是否包含指定的元素;
4.public boolean isEmpty(E e)        判断集合有没有元素;        
5.public int size();                集合中元素的个数;
6.public Object[ ] toArray();        把集合的元素储存到数组中;
7.public void clear();                清空集合中的元素;
-------------------------------------------------------------------------
Iterator<E>接口(迭代器)
常用方法:
boolean hasNext( ) 判断是否达到集合的末尾,是返回false,否返回true;
E next( ) 取出集合中的元素;

Iterator<E>的泛型跟着集合走
Iterator<String> it = coll.iterator( );  集合调方法得到迭代器
b = it.hasNext( );
s = it.nest( );
优化:
while(it.hasNext){
      String s = it.next( );
      System.out.println(s);
}

for(String s : coll){
      System.out.println(s);
}
----------------------------------------------------------------------------------------

       集合按照其储存结构可以分为两大类,分别是单列集合java.util.Collection和双列集合java.util.Map。
       Collection: 单列集合类的跟接口,用于储存一系列符合某种规则的元素,它有两个重要的子接口,分别是java.util.List和java.util.Set。其中,List的特点是元素有序、元素可重复。Set的特点是元素无序,而且不可重复。List接口的主要实现类有java.util.ArrayList和java.util.LinkedList,Set 接口的主要实现类有java.util.HashSet和java.util.TreeSet。

---------------------------------------------------------------------------------------------
迭代器的并发修改异常:ConcurrentModificationException
        在使用迭代器的过程中,修改了集合的长度,增删了集合的元素;就会抛出这个异常。
创建Iterator 的时候会把集合的修改值复制一份给迭代器,之后如果每增、删集合元素一次,集合的修改值会加1,而迭代器的修改值不变,每次next()取元素的时候会先判断迭代器修改值是否与集合修改值一致,如果不一致就会抛出并发修改异常;
用listIterator的时候,添加元素后会把集合修改值复制给listIterator,所以不会抛出异常;

----------------------------------------------------------------------------------------------
泛型:未知的数据类型
创建对象的时候确定泛型的数据类型

定义泛型的方法:
修饰符 <泛型> 返回值类型 方法名称(参数列表(使用泛型))
调用方法时传的数据是什么类型,泛型就是什么类型。

接口的泛型:
1.定义接口的实现类,实现接口,直接指定接口的泛型;
2.接口使用什么泛型,实现类就用什么泛型。创建对象的时候指定泛型的具体类型。

泛型的通配符:
        ?:代表任意的数据类型 ,只能作为方法的参数使用。
泛型的上限:此时的泛型,必须是extends后面类的本身或子类;
泛型的下限:此时的泛型,必须是super后面类的本身或者父类;

数据结构
栈:出口和入口在同一侧,先进后出;
队列:出口和入口在两侧,先进先出;
数组:查询快,增删慢;
链表:查询慢(地址不是连续的),增删快;(单向,无序的;双向,有序的);
红黑树:(排序树:左子输小,右子树大,查询快);(平衡树:左孩子和右孩子相等);红黑树趋近于平衡树,查询速度非常快,查询叶子节点最大次数和最小次数不能超过2倍;节点可以是红色或者黑色的。
----------------------------------------------------------------------------
List接口
        1.有序的集合,存储元素和取出元素的顺序是一致的;
        2.有索引,包含了一些带索引的方法;
        3.允许储存重复的元素。
方法:
        对象.add(int index,E element );
        对象.get(int index);
        E e=对象.remove(int index);
        E e=对象.set(int index,E element);
ArrayList 实现类,不是同步的,是多线程;底层是数组,查询快,增删快;数组中有索引
LinkedList实现类,底层是双向链表,查询慢,增删快;包含大量操作首尾元素的方法;使用特有方法,不能使用多态;也有get()方法,因为类中维护了索引;
Vector实现类,底层是一个数组,同步的,单线程;
--------------------------------------------------------------------------
Set接口
        1.不允许存储重复的元素
        2.不带索引,不能使用for循环遍历
HashSet实现类:
        1.不允许存储重复的元素
        2.没有索引,没有带索引的方法,不能使用for循环
        3.是一个无序的集合
        4.底层是一个哈希表结构(查询速度非常快)哈希表=数组+链表+红黑树
HashSet为什么去重:每次add的时候先调用hashCode和equals方法比较哈希值和内容。

LinkedHashSet实现类:
        1.底层是一个哈希表(数组+链表/红黑树)+链表:多了一条链表记录元素的储存顺序,保证元素有序。
        2.有序
        3.不允许重复
---------------------------------------------------------------------------
可变参数
        使用格式:定义方法时使用
        修饰符  返回值类型  方法名(数据类型...变量名){}
注意:一个方法的参数列表,只能有一个可变参数
         如果方法的参数有多个,那么可变参数必须写在参数列表的末尾;
         终极可变参数:public static viod method ( Object...obj){}
-------------------------------------------------------------------------------
Collections

Collections.addAll(1,2,3,4,5,6)   一次向集合中添加多个元素
Collections.shuffle     打乱集合中元素的顺序
Collections.sort(list)    对list集合升序排序   
        被排序的集合里面储存的元素必须实现Comparable接口中的compareTo方法;排序规则:自己this-参数:升序;

Collections.sort(list,new Comparator<E>(){重写compare方法})

排序规则:对象比指定对象小,返回-1为降序,返回1为升序;返回0相等
        对象比指定对象大,返回1为降序,返回-1为升序;返回0相等


Map<key,value>集合特点
        1.Map集合是一个双列集合
        2.Map集合中的元素,key和value数据类型可以相同,也可以不同
        3.Map集合中的元素,key是不允许重复的,value可以重复;
        4.kay和value是一 一对应
方法:
public V put(K key,V value)   key 不重复,返回null,重复返回被替换的V;
public V get(K key )           key存在,返回对应的值value,不存在,返回null ;
public V remove(K key)  key存在,返回对应的value,key不存在,返回null;
public boolean containsKey(K key)   key存在,返回true,key不存在,返回false ;
public Set<K key> keySet()    V value = map.get(K key)
public Set<Map.Entry<K key ,V value>>  entrySet()   Entry 对象中有 getKey() getValue()方法;
---------------------------------------------------------------------------
HashMap
JDK1.8之后  数组+单项链表、红黑树,查询速度特别快,线程不安全  能存空null
是一个无序的集合

LinkedHashMap
底层是哈希表+链表
是一个有序的集合

Hashtable
效率低 线程安全单线程  不能存空null
----------------------------------------------------------------------------------
Collections集合工具类
Collections.shuffle
Collections.addAll
Collections.sort      

异常
程序执行过程中,出现的非正常情况,最追导致JVM非正常停止,异常本身是一个类

Throwable是异常顶层父类
Error 错误子类(严重问题)  必须修改源代码
Exception  异常子类  (小毛病)编译期异常
        RunTimeException 运行时异常
处理异常:
        1.往上抛,给JVM处理,打印异常,终止程序
        2.try{}catch(){}处理异常,处理完之后程序继续执行
运行时异常,不用我们写抛异常代码 ; 编译期异常,需要我们写抛异常代码,或者try...catch
--------------------------------------------------------------------------------
throw 关键字   写在方法中  我们自己抛异常,我们可以自定义异常的信息    后面可以跟我们自己new出来的异常
格式:
        throw new xxxException("异常产生的原因")
注意:
        1.throw关键字必须写在方法的内部
        2.throw关键字后边new的对象必须是Exception或Exception的子类
        3.throw关键字抛出的指定异常对象,我们就必须处理这个异常对象
                throw关键字后边创建的是RuntimeException或者是                                 RuntimeException的        子类对象,我们可以不处理,默认交给JVM处                        理(打印异常对象,中断程序)

                            throw关键字后边创建的是编译异常(写代码的时候报错),我们就必                须处理这个异常,要么throws,要么try...catch
----------------------------------------------------------------------------------
throws关键字:异常处理的第一种方式,交给别人处理
throws 写在方法上   JVM帮我们抛异常,使用默认的异常信息  后面跟的是异常的类
        
    作用:
        当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象
        可以使用throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者处理(          自己不处理,给别人处理),最终交给JVM处理-->中断处理
        使用格式:在方法声明时使用
    修饰符 返回值类型 方法名(参数列表) throws AAAExcepiton,BBBExcepiton...{
            throw new AAAExcepiton("产生原因");
            throw new BBBExcepiton("产生原因");
            ...
        }
     注意:
        1.throws关键字必须写在方法声明处
        2.throws关键字后边声明的异常必须是Exception或者是Exception的子类
        3.方法内部如果抛出了多个异常对象,那么throws后边必须也声明多个异常
            如果抛出的多个异常对象有子父类关系,那么直接声明父类异常即可
        4.调用了一个声明抛出异常的方法,我们就必须的处理声明的异常
            要么继续使用throws声明抛出,交给方法的调用者处理,最终交给JVM
            要么try...catch自己处理异常

NullPointerException  运行时异常
FileNotFoundException  编译时异常
-----------------------------------------------------------------------------------
try...catch:异常处理的第二种方式,自己处理异常
    格式:
        try{
            可能产生异常的代码
        }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
            异常的处理逻辑,异常异常对象之后,怎么处理异常对象
            一般在工作中,会把异常的信息记录到一个日志中
        }
        ...
        catch(异常类名 变量名){

        }
    注意:
        1.try中可能会抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象
        2.如果try中产生了异常,那么就会执行catch中的异常处理逻辑,执行完毕catch中的处理逻辑,继续执行try...catch之后的代码
          如果try中没有产生异常,那么就不会执行catch中异常的处理逻辑,执行完try中的代码,继续执行try...catch之后的代码
--------------------------------------------------------------------------------------
finally代码块
     格式:
        try{
            可能产生异常的代码
        }catch(定义一个异常的变量,用来接收try中抛出的异常对象){
            异常的处理逻辑,异常异常对象之后,怎么处理异常对象
            一般在工作中,会把异常的信息记录到一个日志中
        }
        ...
        catch(异常类名 变量名){

        }finally{
            无论是否出现异常都会执行
        }
     注意:
        1.finally不能单独使用,必须和try一起使用
        2.finally一般用于资源释放(资源回收),无论程序是否出现异常,最后都要资源释放        
        3. 如果finally有return语句,永远返回finally中的结果,避免该情况.
------------------------------------------------------------------------------------
多个异常使用捕获又该如何处理呢?
            1. 多个异常分别处理。
            2. 多个异常一次捕获,多次处理。
一个try多个catch注意事项:
                catch里边定义的异常变量,如果有子父类关系,那么子类的异常变量必须写在        上边,否则就会报错
            3. 多个异常一次捕获一次处理。
------------------------------------------------------------------------------------
  子父类的异常:
        - 如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类不抛出异常。
        - 父类方法没有抛出异常,子类重写父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出
    注意:
        父类异常时什么样,子类异常就什么样
-------------------------------------------------------------------------------------
自定义异常类:
        java提供的异常类,不够我们使用,需要自己定义一些异常类
    格式:
        public class XXXExcepiton extends Exception | RuntimeException{
            添加一个空参数的构造方法
            添加一个带异常信息的构造方法
        }
     注意:
        1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类
        2.自定义异常类,必须的继承Exception或者RuntimeException
            继承Exception:那么自定义的异常类就是一个编译期异常,如果方法内部抛出了编译期异常,就必须处理这个异常,要么throws,要么try...catch
            继承RuntimeException:那么自定义的异常类就是一个运行期异常,无需处理,交给虚拟机处理(中断处理
----------------------------------------------------------------------------------------
主线程:执行主(main)方法的线程

    单线程程序:java程序中只有一个线程
    执行从main方法开始,从上到下依次执行

    JVM执行main方法,main方法会进入到栈内存
    JVM会找操作系统开辟一条main方法通向cpu的执行路径
    cpu就可以通过这个路径来执行main方法
    而这个路径有一个名字,叫main(主)线程
----------------------------------------------------------------------------------------
创建多线程程序的第一种方式:创建Thread类的子类
    java.lang.Thread类:是描述线程的类,我们想要实现多线程程序,就必须继承Thread类

    实现步骤:
        1.创建一个Thread类的子类
        2.在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么?)
        3.创建Thread类的子类对象
        4.调用Thread类中的方法start方法,开启新的线程,执行run方法
             void start() 使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
             结果是两个线程并发地运行;当前线程(main线程)和另一个线程(创建的新线程,执行其 run 方法)。
             多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
    java程序属于抢占式调度,那个线程的优先级高,那个线程优先执行;同一个优先级,随机选择一个执行


获取线程的名称:
        1.使用Thread类中的方法getName()
            String getName() 返回该线程的名称。
        2.可以先获取到当前正在执行的线程,使用线程中的方法getName()获取线程的名称
            static Thread currentThread() 返回对当前正在执行的线程对象的引用
-------------------------------------------------------------------------------------
设置线程的名称:(了解)
        1.使用Thread类中的方法setName(名字)
            void setName(String name) 改变线程名称,使之与参数 name 相同。
        2.创建一个带参数的构造方法,参数传递线程的名称;调用父类的带参构造方法,把线程名称传递给父类,让父类(Thread)给子线程起一个名字
            Thread(String name) 分配新的 Thread 对象。
---------------------------------------------------------------------------------------
public static void sleep(long millis):使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。
    毫秒数结束之后,线程继续执行
----------------------------------------------------------------------------------------
创建多线程程序的第二种方式:实现Runnable接口
    java.lang.Runnable
        Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run 的无参数方法。
    java.lang.Thread类的构造方法
        Thread(Runnable target) 分配新的 Thread 对象。
        Thread(Runnable target, String name) 分配新的 Thread 对象。

    实现步骤:
        1.创建一个Runnable接口的实现类
        2.在实现类中重写Runnable接口的run方法,设置线程任务
        3.创建一个Runnable接口的实现类对象
        4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象
        5.调用Thread类中的start方法,开启新的线程执行run方法

    实现Runnable接口创建多线程程序的好处:
        1.避免了单继承的局限性
            一个类只能继承一个类(一个人只能有一个亲爹),类继承了Thread类就不能继承其他的类
            实现了Runnable接口,还可以继承其他的类,实现其他的接口
        2.增强了程序的扩展性,降低了程序的耦合性(解耦)
            实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离(解耦)
            实现类中,重写了run方法:用来设置线程任务
            创建Thread类对象,调用start方法:用来开启新线程
--------------------------------------------------------------------------------------
    匿名内部类方式实现线程的创建

    匿名:没有名字
    内部类:写在其他类内部的类

    匿名内部类作用:简化代码
        把子类继承父类,重写父类的方法,创建子类对象合一步完成
        把实现类实现类接口,重写接口中的方法,创建实现类对象合成一步完成
    匿名内部类的最终产物:子类/实现类对象,而这个类没有名字

    格式:
        new 父类/接口(){
            重复父类/接口中的方法
        };
----------------------------------------------------------------------------------------
解决线程安全问题的一种方案:使用同步代码块
    格式:
        synchronized(锁对象){
            可能会出现线程安全问题的代码(访问了共享数据的代码)
        }

    注意:
        1.通过代码块中的锁对象,可以使用任意的对象
        2.但是必须保证多个线程使用的锁对象是同一个
        3.锁对象作用:
            把同步代码块锁住,只让一个线程在同步代码块中执行

解决线程安全问题的二种方案:使用同步方法
    使用步骤:
        1.把访问了共享数据的代码抽取出来,放到一个方法中
        2.在方法上添加synchronized修饰符

    格式:定义方法的格式
    修饰符 synchronized 返回值类型 方法名(参数列表){
        可能会出现线程安全问题的代码(访问了共享数据的代码)

解决线程安全问题的三种方案:使用Lock锁
    java.util.concurrent.locks.Lock接口
    Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。
    Lock接口中的方法:
        void lock()获取锁。
        void unlock()  释放锁。
    java.util.concurrent.locks.ReentrantLock implements Lock接口


    使用步骤:
        1.在成员位置创建一个ReentrantLock对象
        2.在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁
        3.在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁
---------------------------------------------------------------------------------------
  进入到TimeWaiting(计时等待)有两种方式
    1.使用sleep(long m)方法,在毫秒值结束之后,线程睡醒进入到Runnable/Blocked状态
    2.使用wait(long m)方法,wait方法如果在毫秒值结束之后,还没有被notify唤醒,就会自动醒来,线程睡醒进入到Runnable/Blocked状态

    唤醒的方法:
         void notify() 唤醒在此对象监视器上等待的单个线程。
         void notifyAll() 唤醒在此对象监视器上等待的所有线程。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2