面向对象编程(二)

  • 封装(private)
    匿名对象使用的方式:只调用一次
    注意,封装只是私有的一种表现形式。不私有也能封装。
  • 构造函数
    构造函数和一般函数在写法上有不同
    构造函数在对象一建立就运行,
    而一般方法是在对象调用的时候才运行,是给对象添加对象具备的功能。
    一个对象建立,构造方法运行

  • 构造代码块
    作用:给对象初始化,对象一建立就运行,而且优先于构造函数执行。
    和构造函数的区别:
    构造代码块是给所有的对象初始化,构造函数是给特定的对象初始化。
    构造代码块 中定义的是不同对象共性的特性.

  • this关键字

  1. 变量名起的没有意义,可读性非常差
  2. 局部变量和成员变量一样了,局部中有就在局部中使用,没有的话就在成员变量中找,将局部的值赋给成员变量,引出了this关键字
  3. this:看上去,是用于区分局部变量和成员变量同名的情况
  4. this到底代表的是什么
    this:就代表本类的对象,到底代表哪一个呢?
    this代表它所在函数所在对象的引用
    简单说:哪个对象在调用this所在的函数,this就代表哪个对象
  • this关键字在构造函数间的调用
    this语句:用于构造函数间互相调用
    this语句只能放在构造函数的第一行。因为初始化动作要先执行
    不允许死循环调用

面向对象(3)

(继承,final,抽象类,接口)


1.继承(概述)

  • 继承:

1.提高了代码的复用性

2.继承让类与类之间有了关系,有了关系才有了多态的特性。

注意:千万不要为了获取其他类的功能,简化代码而继承。
必须是类与类之间有所属关系才可以继承,所属关系 is a。

java语言中:java只支持单继承,不支持多继承。

因为多继承容易带来安全隐患:当多个父类中定义了相同的功能,当功能内容不同时,子类对象不确定要运行哪一个。
但是java保留了这种机制,并用另一种体现形式来完成表示,多实现。

  • java支持多层继承。
  • 如何使用一个继承体系中的功能?

想要使用体系,先查阅体系父类的描述,因为父类中定义的是该体系的共性功能。

通过了解共性功能,就可以知道该体系的基本功能。那么这个体系已经可以基本使用了
那么在具体调用时,要创建最子类的对象。
因为:1.可能父类不能创建对象 2.创建子类可以使用更多的功能,包括基本的也包括特有的
简单的说,就是查阅父类,创建子类

2.聚集关系

聚集:has a
聚合:
组合:

子父类出现后,类成员的特点
类成员:
1.变量
2.函数
3.构造函数

3.1.子父类中的变量的特点

如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this
super代表的是父类对象的引用

3.2.子父类中的函数的特点

当子类和父类中出现一样的函数时,当子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。
这种情况是函数的另一个特性:重写(覆盖)
当子类继承父类,沿袭了父类的功能,但是功能的内容却和父类不一致。这时没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重写功能内容。

覆盖:
1.子类覆盖父类,必须保证子类权限大于父类权限,否则编译失败
2.静态只能覆盖静态。

3.3.子父类中构造函数的特点–子类的实例化过程

重载:只看重名函数的参数列表。
重写:子类父类方法要一模一样。

子父类中的构造函数:
在对子类对象进行初始化 时,弗父类的构造函数也会运行,那是因为子类的构造函数第一行默认有一条隐式语句super();
super():会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是super()
为什么子类一定要访问父类中的构造函数?
因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类如何对这些数据进行初始化的,所以子类在对象进行初始化时,要先访问一下父类中的构造函数
如果要访问父类中指定的构造函数,可以用super语句来指定。

注意:super语句一定定义在子类构造函数的第一行。

  • 子类的实例化过程:

结论:子类所有的构造函数默认都会访问父类中空参数的构造函数,因为子类每一个构造函数的第一行都有一句隐式的super()
当父类中没有空的构造函数时,子类必须手动通过super或者this语句形式来指定要访问父类中的构造函数。
当然:子类中的构造函数第一行也可以手动指定this语句来访问本类中的构造函数,子类中至少会有一个构造函数会访问父类中的构造函数

4.final关键字

final:最终,作为一个修饰符

  1. 可以修饰类,函数,变量
  2. 被final修饰的类不可以被继承,为了避免被继承,被子类复写功能
  3. 被final修饰的方法不可以被复写
  4. 被final修饰的变量是一个常量只能赋值一次,既可以修饰局部变量,也可以修饰成员变量。
    在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这值起个名字,方便于阅读,而这个值不需要改变,所以加个final修饰。作为常量:常量的书写规范所有字母都大写,如果由多个单词组成,单词间通过_连接。
  5. 内部类定义在类中的局部位置时,只能访问该局部被final修饰的局部变量。

5.抽象类

当多个类中出现相同功能,但是功能的主体不同,这时可以向上抽取,这时只能抽取功能定义,而不抽取功能主题
抽象:看不懂
抽象类的特点:

  1. 抽象方法一定在抽象类中。
  2. 抽象方法和抽象类都必须被abstract关键字修饰。
  3. 抽象类不可以用new创建对象,因为调用抽象方法没意义。
  4. 抽象类中的方法要被使用,必须由子类复写起所有的抽象方法之后,建立子类对象调用。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。

抽象类和一般类没有太大的不同。
该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂的东西。
这些不确定的部分,也是该事物的功能,需要明确出现。但是无法定义主体。

抽象类比一般类多了个抽象函数。就是在类中可以定义抽象方法。
抽象类不可以实例化。
特殊:抽象类中可以不定义抽象方法,这样做仅仅是为了不让该类建立对象。

6.模板方法设计模式

在定义功能时,功能的一部分是确定的,但是有一部分功能时不确定的,而确定的部分在使用不确定的部分,就将不确定的部分暴露出去,

7.接口

  • 接口:初期理解,可以认为是一个特殊的抽象类
    当抽象类中的方法都是抽象的,那么该类可以通过接口的形式实现
    class 用于定义类
    interface 用于定义接口
    接口定义时,格式特点:
  1. 接口中常见定义:常量,抽象方法。
  2. 接口中的成员都有固定的修饰符。常量:public static final
    方法:public abstract
    记住,接口中的成员都是public的
    接口是不可以创建对象的,因为有抽象方法。
    需要被子类实现,子类对接口中的抽象方法全部覆盖后,子类才可以实例化。否则子类是一个抽象类
  • 接口可以被类多实现
    接口与接口之间可以多继承

    8.接口的特点

  1. 接口是对外暴露的规则
  2. 接口是程序的程序扩展
  3. 接口可以用来多实现
  4. 类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口
  5. 接口与接口之间可以有继承关系

面向对象(4)–多态


多态概念

多态:可以理解为事物存在的多种体现形态

多态的扩展性

  1. 多态的体现
    父类的引用指向了自己的子类对象
    父类的引用也可以接收自己的子类对象
  2. 多态的前提
    必须是类与类之间有关系,要么继承,要么实现。
    通常还有一个前提:存在覆盖
  3. 多态的好处
    多态的出现大大的提高程序的扩展性
  4. 多态的弊端:
    提高了扩展性,但是只能用父类的引用访问父类中的成员
  5. 多态的应用

多态–转型

向上转型,向上转型
千万不要出现这样的操作,就是将父类对象转换成子类类型。
我们能转换的是父类应用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。
多态自始至终都是子类对象在做着变化

多态成员的特点

在多态中成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有,编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
在多态中,成员变量的特点:无论编译还是运行,都参考左边(引用型变量所属的类)。
在多态中,静态成员函数的特点:无论编译还是运行,都参考左边(引用型变量所属的类)。

多态的实例

Object类

内部类


内部类访问规则

  1. 内部类可以直接访问外部类中的成员,包括私有
    之所以可以直接访问外部类中的成员,是因为内部类中持有了 一个外部类的引用,格式:外部类名.this
  2. 外部类要访问内部类,必须建立内部类对象。
    直接访问内部类中的成员
    访问格式:
    当内部类定义在外部类的成员位置上,就可以被成员修饰符所修饰。
    比如,private:将内部类在外部类中进行封装。
    static:内部类就具备static的特性。
    当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限。
    在外部其他类中,如何访问内部类的非静态成员呢?

    内部类定义的原则

    当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部事物在使用外部事物的内容。

内部类定义在局部时,

  1. 不可以被成员修饰符修饰
  2. 可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量 、

    匿名内部类

  3. 匿名内部类其实就是内部类的简写格式
  4. 定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。
  5. 匿名内部类的格式:new 父类或者接口(){定义子类的内容}
  6. 其实匿名内部类就是一个匿名子类对象,而且这个对象有点胖。可以理解为带内容的对象
  7. 匿名内部类中定义的方法最多不要超过三个

异常概述

异常:就是程序在运行时出现不正常的情况。
异常的由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述。并封装成对象。其实就是java对不正常情况进行描述后的对象体现
对于问题的划分:两种:一种是严重的问题,一种是不严重的问题

对于严重的,java通过Error类进行描述。
对于Error,一般不编写针对性的代码进行处理
对于非严重的,java通过Exception类进行描述。(可以使用针对性的处理方式进行处理 )

异常try-catch

异常的处理:java提供了特有的语句进行处理
对捕获到的异常对象进行常见的方法操作。
String getMessage

异常声明throws

多异常处理

对多异常的处理。

  1. 声明异常时,建议声明更为具体的异常。这样处理的可以更具体。
  2. 对方声明几个异常,就对应有几个catch块。不要定义多余的catch块
    如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面
    建立在进行catch处理时,catch中一定要具体的处理方式。不要简单的定义一句e.peintStackTrace(),也不要简单的就书写一条输出语句。

自定义异常

项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。所以对于这些特有的问题可以按照java对问题封装的思想。将特有的问题。进行自定义的异常封装。
当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。
要么在内部try catch处理,要么在函数上声明让调用者处理。
发现打印的结果中只有异常的名称,缺没有异常的信息。
因为自定义的异常并未定义信息。
父类中已经把异常信息的操作都完成了。所以子类只要在构造时,将异常信息传递给父类通过super语句。那么直接就可以通过getMessage方法获取自定义的异常。


自定义异常:必须是自定义类继承Exception。原因是:
异常体系有一个特点:因为异常类和异常对象都被抛出。他们都具备可抛性。这个可抛性是Throwable这个体系中的独有特点。只有这个体系中的类和对象才可以被throw和throws操作。

throws 和throw的区别:throws使用在函数上。throw使用在函数内。

throws后面跟的异常类,可以跟多个。用逗号隔开。throw后面跟的是异常对象。

RuntimeException运行时异常。

如果在函数内抛出该异常,函数上可以不用声明,编译一样通过。
如果在函数上声明了该异常。调用者可以不用进行处理。编译一样通过。
之所以不用在函数声明,是因为不需要让调用者处理,当该异常发生,希望程序停止。因为在运行时,出现了无法继续运算的情况,希望停止程序后,对代码尽心修正。
自定义异常时,如果该异常的发生,无法再继续进行运算,就让自定义异常继承RuntimeException
对于异常分两种:

  1. 编译时被检测的异常。
  2. 编译时不被检测的异常(运行时异常。RuntimeException以及其子类)

异常

异常-finally

异常-处理语句其他格式

异常-覆盖时的异常特点

异常在子父类覆盖中的特点:

  1. 子类在覆盖父类时,如果父类的方法抛出异常,子类的覆盖方法,只能抛出父类的异常或该异常的子类。
  2. 如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。
  3. 如果父类或接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。
    如果子类方法发生了异常。那么就必须要进行try处理,绝对不能抛。
    ## 异常练习

    异常–总结

    是什么:是对问题的描述。将问题进行对象的封装

异常体系:Throwable
|–Eroor
|–Exception
|–RuntimeException
异常体系的特点:在异常体系中的所有类以及建立的对象都具备可抛性。也就是说可以被throw和throws关键字所操作。只有异常体系具备这个特点。


throw和throws的用法:
throw:定义在函数内,用于抛出异常对象
throws:定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开
当函数内有throw抛出异常对象,并未进行try处理。必须要在函数上声明,都在编译失败。
注意:除了RuntimeException除外,函数内如果声明的是RuntimeException异常,函数上可以不用声明。


如果函数声明了异常,调用者需要处理。处理方法可以throws可以try
异常有两种:

  1. 编译时被检测异常:该异常在编译时,如果没有处理(没有抛出也没try),编译失败。该异常被标识,代表这可以被处理。
  2. 运行时异常(编译时不检测):在编译时不需要检测,编译器不检查。该异常的发生,建议不处理,让程序停止。需要对代码进行修正。

注意:finally中定义的通常是:关闭资源代码。因为资源必须释放。
finally只有一种情况不被执行。当执行到System.exit(0);finally不被执行


自定义异常:
定义类继承Exception或者RuntimeException

  1. 为了让该自定义类具备可抛性
  2. 让该类具备异常操作的共性方法

自定义异常好处:按照java面向对象的思想,将程序中出现的特有问题进行封装。

  1. 将问题进行封装
  2. 将问题和代码进行分离,方便于阅读
    异常处理的原则:
  3. 处理方式有两种:try或者throws
  4. 调用到抛出异常的功能时,抛出几个,就处理几个
  5. 多个catch,父类的catch放在最下面
  6. catch内,需要定义针对性的处理方式。不要简单的定义printStackTrace输出语句,也不要不写。当捕捉到的异常,本功能处理不了时,可以继续在catch中抛出。 如果该异常处理不了,但并不属于该功能出现的异常。也可以将异常转换后再抛出和该功能相关的异常。 或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去,让调用者知道,并处理。也可以捕获异常处理后,转换新的异常。
    5.

异常的注意事项:
在子类覆盖时:

  1. 子类抛出的异常必须是父类异常的子类或者子集
  2. 如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛

多线程


进程:是一个正在执行中的程序。
每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。
线程:就是进程中的一个独立的控制单元。 线程在控制着进程的执行。
一个进程中至少有一个线程。
java VM启动的时候会有一个进程jav.exe。该进程中至少有一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中。该线程称之为主线程。
扩展:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程。


创建线程

  1. 如何在自定义的代码中,自定义一个线程?
    通过对API的查找,java已经提供了对线程这类事物的描述,就Thread类。
    创建线程的第一种方式:继承Thread类。
    步骤:定义类继承Thread;复写Thread类中的run方法;调用线程的start方法。
    发现运行结果每次都不同。因为多个线程都获取cpu的执行权,CPU执行到谁,谁就运行。(多核除外),cpu在做着快速的切换,以达到看上去是同时运行的效果

创建线程-run和start的特点

为什么要覆盖run方法?
Thread类用于描述线程。该类定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法。
也就是说Thread类中的run方法,用于存储线程要运行的代码。

线程运行状态

原来线程都有自己默认的名称。Thread-编号,该编号从0开始。
static Thread currentThread():获取当前线程对象。
getName():获取线程名称
设置线程名称:setName或者构造函数。


创建线程-runable接口

创建线程的第二种方式:实现Runable接口
步骤:

  1. 定义类实现Runable接口
  2. 覆盖Runable接口中的run方法。 (将线程要运行的代码存放到该run方法中)
  3. 通过Thread类建立线程对象。
  4. 将Runable接口的子类对象作为实际参数传递给Thread类的构造函数。(自定义的run方法所属的对象时Runable接口的子类对象。所以要让线程去指定对象的run方法,就必须明确该run方法所属的对象)
  5. 调用Thread类的start方法开启线程并调用Runable接口子类的run方法。

实现方式和继承方式有什么区别呢?
实现方式:避免了单继承的局限性。在定义线程时,建议使用实现方式。
两种方式的区别:
继承Thread:线程代码存放在Thread子类的run方法中。
实现Runable:线程 代码存在接口的子类的run方法中。


多线程的安全问题

多线程运行出现安全问题的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句值执行了一部分,还没有执行完,另一个线程参与执行。导致共享数据的错误。
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。
java对于多线程的安全问题提供了专业的解决方式。
同步代码块。
synchronized(对象){需要被同步的代码}
对象如同锁。持有锁的线程可以在同步中执行。没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
同步的前提:

  1. 必须要有两个或两个以上的线程。
  2. 必须是多个线程使用同一个锁
    3必须保证同步中只能有一个线程在运行。
    好处:解决了多线程的安全问题。
    弊端:多个线程需要判断锁,较为消耗资源。

多线程-同步函数

同步函数的锁用的是this。
静态同步函数的锁是Class对象


多线程-死锁

#多进程(二)


1线程间通信

线程间通讯:其实就是多个线程在操作同一个资源,但是操作的动作不同。

##2解决安全问题

3等待唤醒机制

wait notify notifyAll 都使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,以为只有同步才具有锁。
为什么这些操作线程的方法要定义在Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识他们所操作线程只有的锁。只有同一个锁上的等待线程,可以被同一个锁上的notify唤醒。不可以对不同锁中的线程进行唤醒。
也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。

StringBuffer


StringBuffer 是字符串缓冲区。是一个容器,

  1. 而且长度是可变化的。
  2. 可以操作多个数据类型。
  3. 最终会通过toString方法变成字符串
    C(create)U(update)R(read)D(delete)
    1.存储
    StringBuffer append():将指定的数据作为参数添加到到已有数据的结尾处
    StringBuffer insert(index,数据):可以将数据 插入到数据指定index位置
    2.删除
    String
    3.获取
    4.修改

StringBuilder

java升级的三个因素:
1.提高效率
2.简化书写
3.安全性

基本数据类型对象包装类

byte Byte
short short
int Integer
long Long
boolean Boolean
float Float
double Double
char Character
基本数据类型对象包装类的最常见作用:就是用于基本数据类型和字符串类型之间做转换。
基本数据类型转成字符串。 基本数据类型+“”或者 基本数据类型.toString(基本数据类型值)
字符串转基本类型。基本数据类型包装类 a=Xxx.parseXxx(String)

集合类


集合框架(体系概述)

为什么出现集合类?
数组是固定长度的,集合是可变长度的。
为什么出现这么多的容器?
因为每一个容器对数据的存储方式都有不同。这个存储方式称之为:数据结构。

##集合框架(共性方法)

迭代器

什么是迭代器?
其实就是集合中元素的取出方式。
把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内容的元素。那么取出方式就被定义成了内部类。而每一个容器的结构数据不同,所以取出的动作细节也不一样。但是都有共性内容:判断和取出。那么可以将这些共性抽取。

List

List集合共性方法

List:元素是有序的,元素可以重复,因为该集合体系有索引。
Set:元素是无序的,不能重复。
List:特有方法:凡是可以操作角标的方法都是该体系特有的方法。
增:add addAll
删: remove
改:set
查:get subList listIterator

ListIterator

在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。
该接口只能通过List集合的ListIterator方法获取。

List集合具体对象的特点

List:
ArrayList:底层的数据结构使用的是数组,查找很快,但是增删稍慢 (可变长度的)
Linkedlist:底层使用的是链表数据结构。特点是增删速度很快,查询稍慢
Vector:底层是数组数据结构。线程同步,被ArrayList替代了 ,现在一般不用了。枚举是Vector特有的取出方式。发现枚举和迭代器很像。其实枚举和迭代是一样的。因为枚举的名称以及方法的名称都过长。所以被迭代器取代了。

LinkedList

LinkedList特有方法:addFirst(),addLast(),getFirst(),getLast(),removeFirst(),removeLast()
JDK1.6出现了替代方法。
offerFriest peekFirst poolFirst
堆栈:先进后出
队列: 先进先出 FIFO
List集合判断元素是否相同,依据的是元素的equals方法。

##set
set:元素是无序(存入和取出的顺序不一定一致)
set集合的功能和collection是一致的。
HashSet:底层数据结构是哈希表。HashSet是如何保证元素的唯一性的呢?是通过元素的两个方法。hashCode和equals来完成。如果元素的HashCode值相同,才会判断equals是否为true,如果元素的hashCode不同,不会判断equals。
注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。

集合框架2


##set
set:无序,不可以重复元素。
hashset:数据结构是哈希表,线程非同步的,保证元素唯一性的原理,判断元素的hashCode值是否相同。如果相同,判断equals
TreeSet:可以对set集合中的元素进行排序。
底层数据结构是二叉树。保证元素唯一性的依据:compareTo return 0
往TreeSet集合中存储自定义对象学生。想按照学生的年龄进行排序。
记住:排序时,当主要条件相同时,一定判断一下次要条件。

二叉树

TreeSet排序的第一种方式:让元素自身具备比较性。元素需要事项compareable接口,覆盖compareTo方法。这种方式也称为元素的自然顺序,或者叫做默认顺序。
TreeSet排序的第二种方式:当元素自身不具备比较性时,或者具备的比较性不是锁需要的。这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。
当元素自身不具备比较性,或者具备的比较性不是所需要的。这时需要让容器自身具备比较性,定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主。定义一个类实现Comparator接口,覆盖compare方法。

泛型

JDK1.5之后出现的新特性,用于解决安全问题,是一个安全机制。
好处:

  1. 将运行时期出现问题转移到编译时期,便于程序员解决。
  2. 避免了强制转换的麻烦。
    泛型格式:通过<>来定义要操作的引用数据类型
    在使用java提供的对象时,什么时候写泛型?
    通常在集合框架中很常见,只要见到<>就要定义泛型。其实<>就是用来接收类型的。当使用集合时,将集合中的要存储的数据类型放到<>中即可。

    泛型类

    泛型类:带泛型的类。
    当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展,现在定义泛型完成扩展。

    泛型方法

    泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象没明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义到方法上。

    静态方法泛型

    特殊之处是:静态方法不可以访问类上定义的泛型,如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。

    泛型接口

    泛型限定

    ?: 通配符,也可以理解为占位符。
    泛型的限定: ? extends E:可以接收E类型或者E的子类型。上限
    ? super E:可以接收E类型或者E的父类型。下限
    

集合(MAP)

Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。

  1. 添加。
  2. 删除。clear()
  3. 判断。
  4. 获取。
    Map:Hashtable:底层是哈希表数据结构,不能存入null键null值,是线程同步的。
    HashMap:底层是哈希表数据结构,允许使用null键null值,该集合是不同步的。
    TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。–和Set很像,其实Set底层就是使用了Map集合。

    Map子类对象的特点

    Map共性方法

    Map-keySet

    map集合的两种取出方式:
  5. keySet:将map中所有的键存入到set集合。因为set具备迭代器。所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。
  6. entrySet
    Set<Map.Entry<K,V>> entrySet:将Map集合中的映射关系存入了set集合中,而这个关系的数据类型就是:Map.entry。其实Entry也是一个借口,它是Map接口中的一个内部接口。

    Map练习

    当发现有映射关系时,可以选择map集合。因为map集合中存放的就是映射关系。
    什么时候使用map集合?当数据之间存在映射关系时,就要先想map集合
    ##map扩展知识
    map集合被使用是因为具备映射关系。

集合(工具类)


sort

max

binarySerch

替换反转

reserveOrder

Synlist

Arrays

用于操作数组的工具类,里面都是静态方法。

集合变数组

1.指定类型的数组到底要定义多长呢?
当指定类型的数组长度小于集合的size,那么该方法会创建一个新的数组,长度为集合的size。当指定类型的数组长度小于了集合的size,就不会创建新数组,而是使用传递进来的数组,所以创建一个刚刚好的数组最优。
2.为什么要将集合变数组?
为了限定对元素的操作。

##增强for循环

##可变参数
方法的可变参数注意:
可变参数一定要定义在参数列表的最后面。

##静态导入
当类名方法重名时,需要指定具体的包名。
当方法重名时,指定具备所属的对象或者类

#其他对象


System

可不可以在jvm启动时,动态加载一些属性信息。

##Runtime对象
该类并没有提供构造函数。说明不可以new 对象,那么会直接想到该类中的方法都是静态的,发现该类中海油非静态方法。
说明该类肯定会提供了方法获取本类对象,而且该方法是静态的,并返回值类型是本类类型。
由这个特点可以看出该类使用了单例设计模式执行。

##Date

Math

#IO流


BufferedWriter

缓冲区的出现是为了提高流的操作效率而出现的。所以在创建缓冲区之前,必须要先有流对象。
为了 提高字符写入流效率,加入了缓冲技术,只要将需要提高效率的流对象作为参数传递给缓冲区的构造函数即可。
记住只要用到缓冲区,就要记得刷新。
其实关闭缓冲区,其实就是在关闭缓冲区的流对象。
该缓冲区中提供了一个跨平台的newLine()

BufferedReader

为了提高效率,加入缓冲技术。将字符读取流对象作为参数传进缓冲对象的构造函数。
readLine方法返回的时候只返回回车符之前的数据内容,并不返回回车符。
readLine方法的原理:无论是读取一行,还是读取多个字符,其实最终都是在硬盘上一个个读取。所以最终使用的还是read方法一次读一个的方法。

MyBufferedReader

装饰设计模式

定义:当想要对已有的对象进行功能增强时,可以定义一个类,将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的该类称为装饰类。
装饰类通常会通过构造方法接收被装饰的对象。并基于被装饰的对象的功能,提供更强的功能。

装饰和继承的区别

装饰模式比继承要灵活,避免了继承体系臃肿。而且降低了类与类之间的关系。
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能。所以装饰类和被装饰类通常都属于一个体系中的。

LineNumberReader

字符流和字节流

FileReader:
FileWriter:
字节流:
InputStream:
OutputStream:

复制一个图片

思路:
1.用字节读取流对象和图片关联。
2.用字节写入流对象创建一个图片文件,用于存储获取到的图片数据。

  1. 通过循环读写,完成数据的存储。
  2. 关闭资源

    读取转换流

    写入转换流

    流操作的基本规律

    最痛苦的就是流对象有很多,不知道该用哪一个。
    通过两个明确来完成。
    1.明确源和目的。
    源:输入流。InputStream Reader
    目的:输出流。OutputStream Writer
    2.操作的数据是否是纯文本。
    是:字符流。
    否:字节流。
    3.当体系明确后,再明确要使用哪个具体的对象。
    通过设备来进行区分:
    源设备:内存,硬盘,键盘
    目的设备:内存,硬盘,控制台。

    File类

    用来将文件或文件夹封装成对象。
    方便对文件与文件夹的属性信息进行操作。
    File对象可以作为参数传递给

    File类的常见方法

    1.创建
    boolean createNewFile()
    boolean mkdir()
    boolean mkdirs()

2.删除
boolean delete() 删除失败返回false
void deleteOnExit() 在程序退出时删除文件

3.判断
boolean exists() 文件或目录是否存在。
记住在判断文件对象是否是文件或者目录时,必须要先判断该文件对象封装的内容是否存在,通过exists判断。
boolean isFile()
boolean isDirectory()

4.获取信息。
String getName()
String getParent() 该方法返回的是绝对路径中的父目录,如果获取的是相对路径,则返回null。
String getPath()
File getAbsoluteFile()
long lastModified()
long length()

文件列表

static File[] listRoots()
String[] list() 调用list方法的必须是封装的一个目录。该目录还必须存在。

列出目录下所有的内容

递归
递归要注意:
1.限定条件。
2.要注意递归的次数,尽量避免内存溢出。

删除一个带内容的目录

删除原理:
在Windows中,删除目录从里面往外删除的。既然是从里往外删除,就需要用到递归。

创建java文件列表

properties

properties是hashtables的子类,也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串。是集合中和IO技术相结合的集合容器。
该对象的特点:可以用于键值对形式的配置文件。

##IO包中的其他类
打印流:该流提供了打印方法,可以将各种数据类型的数据都原样打印。
字节打印流
PrintStream
构造函数可以接收的参数类型。

  1. file对象。File
  2. 字符串路径
  3. 字节输出流
    字符打印流
    PrintWrite
  4. file对象。File
  5. 字符串路径
  6. 字节输出流

合并流和切割文件

对象的序列化

管道流

RandomAccessFile

该类不是算是IO体系中子类,而是继承自Object。
但是它是IO包中的成员,因为它具备读和写功能。颞部封装了一个数组,而且通过指针对数组的元素进行操作。
可以通过getFilePointer获取指针位置。同时可以通过seek改变指针位置。
其实完成读写的原理就是内部封装了字节输入流和输出流。通过构造函数可以看出,该类只能操作文件。而且操作文件还有模式。
该对象的构造函数要操作的文件不存在,会自动创建。如果存在不会覆盖。

ByteArrayStream


GUI(图形用户界面)


GUI

Awt与 Swing

java.Awt: Abstract Window ToolKit (抽象窗口
工具包),需要调用本地系统方法实现功能。属
重量级控件。
javax.Swing:在AWT的基础上,建立的一套图
形界面系统,其中提供了更多的组件,而且完全
由Java实现。增强了移植性,属轻量级控件。