以下是当初学java se时随手记的,没什么时间整理,不能作为教程,仅能作为复习材料。
extends 继承的关键字
abstract 抽象的关键字
implements 接口的实现关键字
throws 声明该功能有可能很出现问题的关键字
对于变量 final 和static的区别
static 只是在内存中独立,可以修改 但是final变量不可以被修改
 
 

多态

多态:可以理解为事物存在的多种体现形态
1.多态的体现
父类的引用指向了自己的子类对象。父类的引用也可以接收自己的子类对象 。
2.多态的前提
必须是类与类之间有关系,要么继承,要么实现。通常还有一个前提,就是存在覆盖。
3.多态的好处
多态的出现大大的提高了程序的扩展性
4.多态的弊端
提高了扩展性,但是只能使用父类的引用访问父类中的成员。
5.多态的应用
ex:主板PCI   数据库Dao类。
6.多态的出现代码中的特点(多态使用的注意事项)
 
在多态中(父类指向子类对象)非静态成员函数的特点:(非静态才有override的特性)
在编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有编译通过如果没有,编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时编译看左边,运行看右边。
在多态中,成员变量的特点:
无论编译和运行都参考左边(引用型变 所属的类)。
在多态中,静态成员函数的特点:
无论编译和运行都参考左边。
 
 

Object

Object:是所有对象的直接或者间接父类,该类中定义的肯定是所有对象都具备的功能。
Object类中已经提供了对对象是否相同的比较方法。
如果自定义类中也有比较相同的功能,没有必要重新定义。
只要沿袭父类中的功能,建立自己特有的比较内容极客,这就是覆盖。
 
 

内部类

内部类的访问规则:
1.内部类可以直接访问外部类中的成员,包括私有。之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用。格式  外部类名.this
2.外部类要访问内部类必须建立内部类对象。
访问格式:
1.当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类(Outer类外其他类)中,可以直接建立内部类对象。
格式:外部类名.内部类名 变量名 = 外部类对象.内部类对象。
Outer.Inner in = new Outer().new Inner();
2.当内部类在成员位置上,就可以被成员修饰符所修饰。
比如,private:将内部类在外部类中进行进行封装。
static :内部类就具备了static的特性。当内部类被静态修饰后,只能直接访问外部类中的静态成员,出现了访问局限。
在外部中其他类中,如何直接访问静态内部类的非静态成员呢?
new Outer.Inner().function();
在外部中其他类中,如何直接访问静态内部类的静态成员呢?
new Outer.Inner.function();
注意:当内部类中定义了静态成员,该内部类必须是static的。当外部类中的静态方法访问内部类时,内部类也必须是static的。
当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部事物在使用外部事物中的内容。
内部类定义在局部时:
1.不可以被成员修饰符修饰。
2.可以直接访问外部类中成员,因为还持有外部类总的引用,但是不可以访问它所在的局部中变量,只能访问被final修饰的局部变量。
 
 

匿名内部类

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

异常

异常:就是程序在运行时出现不正常情况。
异常由来:问题也是现实生活中的一个具体的事物,也可以通过java的类的形式进行描述,其实就是java对不正常情况进行描述后的对象体现。
对于严重的,java通过Error类进行描述。
对于Error一般不编写针对性的代码对其进行处理。
对于非严重的,java通过Exception类进行描述。
对于Exception可以使用针对性的处理方式进行处理。
无论Error或者Exception都具有一些共性内容。
比如:不正常情况的情况,引发原因等。
Throwable(java语言中所有错误或异常的超类(父类))
|–Error
|–Exception
2.异常的处理
java提供了特有的语句进行处理。

try{
    需要被检测的代码;
}catch(异常类 变量){
    处理异常的代码;
}finally{
    一定会执行的语句;
}

3.对捕获到的异常对象进行常见方法操作
String getMessage();获取异常的信息。
对多异常的处理。
1.声明异常时,建议声明更为具体的异常,这样处理的可以更具体。
2.对方声明几个异常,就对应有几个catch块,不要定义多余的catch块。
3.如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。
建议在进行catch处理时,catch中一定要定义具体处理方式,不要简单的定义一句 e.printStackTrace();也不要简单的就书写一条输出语句。
 
 

自定义异常

因为项目中会出现特有的问题,而这些问题并未被java所描述并进行封装。所以对于这些特有的问题可以按照java的对问题的封装思想。将特有的问题,进行自定义的异常封装。
自定义异常
当在函数内部出现了throw抛出异常对象,那么必须要给对应的处理动作。
要么在内部 try catch处理。
要么在函数上声明让调用者处理。
一般情况下,在函数内出现异常,函数上需要声明。
如何定义异常信息?
因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息传递给父类通过super语句。那么就可以直接通过getMessage方法获取自定义的异常信息。
自定义异常必须是自定义类集成Exception
继承Exception原因
异常体系又一个特点:因为异常类和异常对象都需要被抛出,他们都具备可抛性这个可抛性是Throwable这个体系中独有的特点。只有这个体系中的类和对象才可被throw和throws操作
throw和throws的区别
1.throws使用在函数上,throw使用在函数内。
2.throws后面跟的的异常类,可以跟多个,用“,”隔开,throw后面跟的是异常对象。
Exception中又一个特殊的子类异常叫做RuntimeException
如果在函数内抛出该异常,函数上可以不用声明,编译一样通过
如果在函数上声明了该异常,调用者可以不用进行处理,编译一样通过
之所以不用在函数声明,是因为不需要让调用者处理
当该异常发生,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序后程序员对该代码进行修正。
自定义异常时:如果该异常的发生,无法再继续进行运算,就让自定义异常继承RuntimeException。
对于异常分为两种:
1.编译时被检测的异常
2.编译时不被监测的异常(运行时异常。RuntimeException以及其子类)
finally代码块:定义一定执行的代码。通常用于关闭资源。
异常在子父类覆盖中的体现:
1.子类正在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。

Exception
    |---AException
        |---BException
    |---CException
  //如果父类抛出A异常,子类只能抛出A或B异常

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

异常的总结

异常是什么?
异常是对问题的描述,将问题进行对象的封装。
异常体系

Throwable
    |---Error
    |---Exception
        |---RuntimeException

 
异常体系的特点
1.异常体系中的所有类以及建立的对象都具备可抛性。
2.也就是说可以被throw和throws所操作。
3.只有异常体系具备这个特点
throw和throws的用法:
throw定义在函数内,用于抛出异常对象
throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。
当函数内有throws抛出异常对象,并未进行try处理,必须要在函数上声明,否则编译失败。
注意:RuntimeException除外。也就是说,函数内如果抛出RuntimeException异常,函数上可以不用声明
如果函数声明了异常,调用者需要进行处理,处理方式可throws可try。
异常有两种:
编译时被检测异常:
该异常在编译时,如果没有处理(没有throws也没有try)那么编译失败
该异常被标识代表着可以被处理。
运行时异常(编译时不检测):
在编译时不需要处理,编译器不检查
该异常发生,建议不处理,让程序停止,需要对代码进行修正。
异常处理的语句:
 
有三种结合的方式   try catch、try catch finally、try finally。
注意:
1.finally中通常定义的是关闭资源代码,因为资源必须要释放
2.finally只有一种情况不会执行,当执行到System.exit(0)(jvm系统退
出),finally不会被运行。
自定义异常:
定义类继承Exception或者RuntimeException
1.是为了让该自定义类具备可抛性
2.让该类具备操作异常的共性方法
当要定义自定义异常的信息时,可以使用父类已经定义好的功能。
异常信息传递给父类的构造函数
自定异常:
按照java的面向对象思想,将程序中出现的特有问题进行封装。
异常的好处:
1.讲问题进行封装
2.讲异常流程代码和问题处理代码相分离,方便阅读。
异常的处理原则:
1.处理方式有两种:try或者throw
2.调用到抛出异常的功能时,抛出几个,就处理几个。一个trt对应多个catch。
3.多个catch,父类的catch放到最下面。
4.catch内需要定义针对性的处理方式,不要简单的定义printStackTrace,或者输出   语句,也不要不写。当捕获到的异常,本功能处理不了时,可以继续在catch throw。

try{
    throw new AException();
}catch(AException e){
    throw e;
}

 
如果该异常处理不了,但是并不属于该功能出现的异常,可以将异常转换后,在抛出和该功能相关的异常,或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去。
让调用者知道,并处理,也可以将捕获异常处理后,转换新的异常。

try{
    throw new AException();
}catch(AException e){
    throw new BException;
}

比如汇款的例子
异常的注意事项:
在子类覆盖时:
1.子类抛出的异常必须是父类抛出异常的子类或者子集。
2.如果父类或者借口没有异常抛出时,子类覆盖出现异常只能try不能throws
 
 

包(package)

1.对类文件进行分类管理
2.给类提供多层命名空间
3.写在程序文件的第一行
4.类名的全称是包名.类名
5.包也是一种封装的形式
总结:
包与包之间进行访问,被访问的包中的类以及类中的成员,需要public修饰。
不同包中的子类还可以直接访问父类中被protected权限修饰的成员。
包与包之间可以使用的权限只有两种  public  protected
 

public     protected   protect  default(默认)   private
同一个类中    ok      ok      ok              ok
用一个包中    ok      ok      ok
子类       ok      ok
不同包中     ok

import:
导入 的是包中的类
建议:不要写通配符“*”,用什么写什么
建立包名不要重复,可以使用url来完成定义,url是唯一的。
 
 

多线程

进程:是一个正在执行中的程序,没一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元
线程:就是进程中的一个独立的控制单元,线程控制着进程的执行
一个进程中至少有有一个线程
java VM 启动的时候会有一个进程叫做java.exe。
该进程中至少有一个线程在负责java程序的执行,而且这个线程运行的代码存在于main方法中,该线程称之为主线程。
扩展:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程。
1.如何在自定义的代码中,自定义一个线程呢?
通过对api的查找,java已经提供了对线程这类事物的描述,就Thread类
创建线程的第一种方式:继承Thread类。
步骤:
1.定义类继承Thread
2.复写Thread类中的run方法。目的:将自定义的代码存储在run方法汇总,让线程运行。
3.调用线程的start方法,该方法有两个作用,
发现运行结果每一次都不同
因为多个线程都获取cpu的执行权,cpu执行到谁,谁就运行明确一点,在某一时刻,只能又一个程序在运行,(多核除外),cpu在做着快速的切换,以达到看上去是同时运行的效果。
我们可以形象的把多线程的运行行为在互相抢夺cpu的执行权。
这就是多线程的一个特性,随机性,谁抢到谁执行,至于执行多长时间,cpu说的算。
为什么要覆盖run方法呢?
Thread类用于描述线程。
该类定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法。
也就是说Thread类中的run方法,是用于存储线程要运行的代码。
static Thread currentThread();获取当前线程对象
getName();获取线程的名称。
设置线程的名称:setName或者构造函数。
创建线程的第二种方式:实现Runnable接口
步骤:
1.定义类实现Runnable接口。
2.覆盖Runnable接口中的run方法。将宣称要运行的代码存放在run方法中
3.通过Thread类建立线程对象。
4.将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。为什么要讲Runnable接口的子类对象传递给Thread的构造函数因为自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程去执行指定对象的run方法,就必须明确该run方法所属的对象
5.调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
实现方式和继承方式有什么区别:
实现方式好处,避免了单继承的局限性。在定义线程时,建议使用实现方式
继承Thread:线程代码存放在Thread子类的run方法中
实现Runnable:线程代码存在接口的子类的run方法中
通过分析,发现,打印 0,-1,-2等错票(模拟买票系统)
多线程的运行出现了安全问题
问题的原因:
当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完另一个线程参与进来执行,导致共享数据的错误
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中其他线程不可以参与执行。
java对于多线程的安全问题提供了专业的解决方式:同步代码块
同步代码块:

synchronized(对象){
    需要被同步的语句
}

 
对象如同锁,持有锁的线程可以在同步中执行,没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁
同步的前提:
1.必须要有两个或两个以上的线程。
2.必须是多个线程使用用一个锁
必须保证同步中只能又一个线程在运行
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源。
同步函数用的是哪一个锁呢?
函数需要被对象调用,那么函数都又一个所属对象的引用,就是this所以同步函数使用的锁是this
如果同步函数被静态修饰后,使用的锁是什么?
通过验证,发现不是this,因为静态方法中也不可以定义this静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象(类名.class)该对象的类型是Class
静态的同步方法:使用的锁是该方法所在类的字节码文件对象。 类名.class
单例设计模式
饿汉式:
 

class Single{
  private static final Single s = new Single();
  private Single(){
    代码;
  }
  public static Single getInstance(){
    return s;
  }
}

 
懒汉式:
 

class Single{
  private static Single s = null;
  private Single(){
    代码;
  }
  public static synchronized Single getInstance(){//在这加同步比较低效
    if(s==null){
    s = new Single();
  }
  return s;
}

 

线程间通讯

其实就是多个线程在操作同一个资源,但是操作的动作不同
wait() notify()  notifyAll()
都使用在同步中,因为要对持有监视器(锁)的线程操作,所以要使用在同步中,因为只有同步才具有锁的概念
为什么这些操作线程的方法要定义在Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识他们所操作线程只有的锁,只有同一个锁上的被等待线程可以被同一个锁上的notify()唤醒,不可以对不同锁中的线程进行唤醒,也就是说 等待和唤醒必须是同一个锁,而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。
对于多个生产者和消费者
为什么要定义while判断标记?
让被唤醒的线程再一次判断标记
为什么定义notifyAll()
因为需要唤醒对方线程,只用notify(),容易出现值唤醒本方线程的情况,导致程序中的所有线程都等待
JDK1.5 中提供了多线程升级解决方案
将同步synchronized替换成现实Lock操作
将Object中的wait notify notifyAll 替换了Condition对象
该对象可以lock锁,进行获取
在示例(生产者消费者)实现了本方只唤醒对方的操作
stop方法已经过时 那么如何停止线程?
只有一中 run方法结束,开启多线程运行,运行代码通常是循环结构
只要控制住循环,就可以让run方法结束,也就是线程结束
特殊情况:
当线程处于冻结状态
就不会读取到标记,那么程序就不会结束
当没有指定的方式让冻结的线程回复到运行状态时,这是需要对冻结进行清除。
Thread类中提供了方法 interrupt()
join:
当A线程执行到了B线程的join方法时,A就会等待,等B线程执行完,A才会执行join可以用来临时加入线程执行
 
 

String类

String类用于描述字符串事物
那么他就提供了多个方法对字符串进行操作
常见的操作有那些?
“abcd”
1.获取
1.1 字符串中包含的字符数,也就是字符串的长度
int length();获取长度
1.2 根据位置获取位置上的某个字符
char charAt(int index);
1.3 根据字符获取该字符在字符串中的位置
int indexOf(int ch);返回的是ch在字符串中第一次出现的位置
int indexOf(int ch,int fronIndex);从fromIndex位置开始,获取ch在字符串中第一次出现的位置
int indexOf(String str);返回的是str在字符串中第一次出现的位置
int indexOf(String str,int fronIndex);从fromIndex位置开始,获取str在串中第一次出现的位
2.判断
2.1 字符串中是否包含一个子串
boolean contains(str);特殊之处:indexof(str):可以索引str第一次出现的位置。如果返回-1
说明str不在字符串中所以,也可以用于对指定判断是否包含
if(str.indexOf(“aa”)!=-1)而且该方法既可以判断,还可以获取出现的位置
2.2 字符串中是否有内容
boolean isEmpty();原理就是判断是否为0
2.3 字符串中是否是以指定内容开头
boolean startWith(srt);
2.4 字符串中是否是以指定内容结尾
boolean endWith(srt);
2.5 判断字符串内容是否相同,复写了Object类中的equals方法
boolean equals(str);
2.6 判断内用是否相同,忽略大小写
boolean equalsIgnoreCase();.
3.转换
3.1 将字符数组转成字符串
构造函数:String(char[])
String(char[],offset,count)将字符数组中的一部分转成字符串
静态方法:static String copyValueOf(char[])
static String copyValueOf(char[],data,int offset,count)
static String valueOf(char[])
3.2 将字符串转成字符数
char[] toCharArrey();
3.3 将字节数组转成字符串
String(byte[])
String(byte[],offset,count)将字符数组中的一部分转成字符串
3.4 将字符串转成字节数组
byte[] getByts();
3.5 将基本数据类型转成字符串
static String valueOf(int)
static String valueOf(double)
3+”” =  String.valusOf(3)
特殊:字符串和字节数组在转换过程中,是可以指定编码表的。
4.替换
String replace(oldchar,newchar);//如果要替换的字符不存在,返回的还是原串
5.切割
String[] split(regex);
6.子串
获取字符串中的一部分
String substring(begin);//从指定位置到结尾
String substring(begin,end);//从指定位置到指定位置-1
7.转换 去除空格 比较
7.1 将字符串转成大写或小写
String toUpperCase()
String toLowerCase()
7.2 将字符串两端的多个空格去除
String trim()
7.3 对两个字符串进行自然顺序的比较
int compareTo(string)
 
 

StringBuffer

是一个容器
特点:而且长度是可变化的可以直接操作多个数据类型最终会用过toString方法变成字符串
C create  U update R  read D delete
1.存储
StringBuffer append();将指定数据作为参数添加到已有数据的结尾处
StringBuffer insert(index,数据);可以将数据插入到指定index位置
2.删除
StringBuffer delete(start,end);删除缓冲区中的数据,包含start不包含end
StringBuffer deleteCharAt(index);删除指定位置的字符
3.获取
char charAt(int index);
char indexOf(String str);
int lastIndexOf(String str)
int length()
String substring(int start,int end)
4.修改
StringBuffer replace(start,end,string)
void setCharAt(int index,char ch)
5.反转
StringBuffer reverse();
6.将缓冲区中的指定数据存储到指定数组中
void getChars(int srcBegin,int srcEnd,char[] dst,int dstBegin)(src源 dst 目的)
在JDK1.5版本之后出现了StringBuilder
StringBuffer是线程同步
StringBuilder是线程不同步
JDK升级的三个因素:
1.提高效率
2.简化书写
3.提高安全性
基本数据类型对象包装类

类型     对象
byte   Byte
short  Short
int    Integer
long   Long
boolean Boolean
float  Float
double  Double
char    Character

基本数据类型包装类的最常用作用
就是用于基本数据类型和字符串类型之间的转换
基本数据类型转成字符串
基本数据类型+“”
基本数据类型.toString(基本数据类型值);
字符串转成基本数据类型
静态方法
parseInt(String str)
xxx a = Xxx.parseXxx(String);
非静态方法
Integer i =new Integer(“123”)l;
int num = i.intValue();
十进制转成其他进制
toBinaryString()      2
toHexString()         16
toOctalString()        8
其他进制转成十进制
parseInt(string,radix)

集合框架

为什么会出现这么多的容器呢?
因为每一个容器对数据的存储方式都有不同,这个存储方式我们称之为:数据结构
add方法的参数类型是Object。以便于接收任意类型的对象
集合中存储的都是对象的引用(地址)
什么是迭代器呢
其实就是集合的取出元素的方式
就把取出方式定义在集合的内部这样取出方式
就可以直接访问集合内容的元素
那么取出方式就被定义成了内部类
而每一个容器的数据结构不同
所以取出的动作细节也不一样,但是都有共性内容,判断和取出,那么可以将写共性抽取
那么这些内部类都符合一个规则,就是Iterator
如何获取集合的取出对象呢?
通过一个对外提供的方法 iterator();
Collection

    |--List 元素有序而且可以重复 因为该集合体系有索引
        |---ArreyList    底层的数据结构使用的是数组结构 线程不同步
        |---LinkedList    底层使用的是链表数据结构
        |---Vector    底层是数组数据结构  线程同步  被ArreyList替代
    |--Set  元素是无序的不可以重复 因为没有索引

 

List:

特有方法:凡是可以操作角标的方法都是该体系特有的方法
增:
add(index,element)
addAll(index,Collection)
删:
remove(index)
改:
set(index,element)
查:
get(index)
subList(from,to)
listIterator()
List集合特有的迭代器:ListIterator是Iterator的子接口
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生并发修改异常ConcurrentModificationException所以在迭代时,只能用迭代器的方法操作元素,可是Iterator方法是有限的只能对元素进行判断取出删除的操作,如需要其他的操作如添加修改等,就需要使用其子接口ListIterator接口,该接口只能通过List集合的ListIterator来获取
枚举就是Vector特有的取出方式(迭代器 循环get)
发现枚举和迭代器很像
其实枚举和迭代是一样的,因为枚举的名称以及方法的名称都过长,所以被迭代器取代
LinkedList特有方法:
addFirst()
addLast()
获取元素但不删除元素
getFirst()
getLast()
获取元素但是元素被删除
removeFirst()
removeLast()
如果集合中没有元素,会出现NoSuchElementException异常
在JDK1.6中出现了替代方法
offerFirst()
offerLast()
peekFirst()
peekLast()
pollFirst()
pollLast()
如果集合中没有元素,会返回null
List集合判断元素是否相同,依据的是元素的equals方法

Set:

无序:存入和取出的顺序不一定一致
Set功能和Collection是一致的

    |--Set
        |---HashSet    低层数据结构是哈希表

HashCode是如何保证元素的唯一性的呢?
是通过元素的两个方法 hashCode和equals来完成的,如果元素的hashCode值相同才会判断equals是否为true,如果元素的hashCode值不同,那么不会调用equals
注意:对于判断元素是否存在以及删除等操作,依赖的方法是,元素的hashCode和equals方法
|—TreeSet    可以对Set集合中的元素进行排序
排序时:当主要条件相同时,一定要判断一下次要条件
低层数据结构是二叉树
保证数据唯一性的依据是 compareTo方法的return 0;
TreeSet排序的第一种方式:
让元素自身具备比较性,元素需要实现Comparable方法,覆盖compareTo方法,这种方法也成为元素的自然顺序,或叫做默认排序
TreeSet排序的第二种方式:
当元素自身不具备比较性或者具备的比较性不是所需要的,这时候需要让集合自身具备比较性
在集合初始化时,就有了比较方式
当两种排序都存在时,以比较器为主
比较器:定义一个类实现Comparator接口覆盖compare方法

泛型

泛型:JDK1.5版本以后出现的新特性,用于解决安全问题,是一个安全机制
好处:
1.将运行时期出现的问题ClassCastException转移到了编译时期,方便了程序员解决问题,让运行时期问题减少,安全。
2.避免了强制转换的麻烦。
泛型格式:通过<>在定义要操作的引用数据类型
在使用java提供的对象时,什么时候使用泛型呢?
通常在集合框架中很常见
只要见到<>就要定义泛型
其实<>就是用来接收类型的
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可
什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候。早期定义Object来完成扩展,现在定义泛型来完成扩展。
泛型类定义的泛型,在整个类中有效,如果被方法使用
那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了,为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上
静态方法不可以访问类上定义的泛型,如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上
? 通配符。也可以理解为占位符
泛型的限定:

1.<? extands E> 可以接收E类型或者E的子类型,上限限定
2.<? super E> 可以接收E类型或者E的父类,下限限定

Map

Map集合:该集合存储键值对,一对一往里存,而且要保证键的唯一性
1.添加
put(K key,V value)
putAll(Map,m)
2.删除
clear()
remove(Object key)
3.判断
containsKey(Object key)
containsValue(Object value)
isEmpty()
4.获取
value get(Object key)
size()
values()
entrySet()
keySet()
Map

  |--Hashtable    底层是哈希表数据结构,不可以存入null键null值 该集合是线程同步的
  |--HashMap      底层是哈希表数据结构,允许使用null键null值  该集合是线程不同步的
  |--TreeMap      底层是二叉树数据结构,线程不同步。可以用于给Map集合中的键进行排序和Set很像,其实Set集合低层就是使用的Map集合

 
可以通过get方法的返回值来判断一个键是否存在,通过返回null来判断添加元素如果出现相同的键,那么后添加的值会覆盖原有的键对应的值,并put方法会返回被覆盖的值
map集合的两种取出方式:
1.keySet()    将map中所有的键存入到set集合,因为set集合具备迭代器,所以可以通过迭代方式取出所有的键,然后根据get方法,获取每一个键的对应值
Map集合的取出原理:
将map集合转换成Set集合,再用迭代器取出
2.<Map.Entry<k,v>> entrySet()将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是Map.Entry
Map.Entry 其实Entry也是一个接口,它是Map接口中的一个内部接口

interface Map{
  public static interface Entry{
    public abstract Object getKey();
    public abstract Object getValue();
  }
}

 
map扩展知识:
map集合被使用是因为具备映射关系
 
 

集合框架工具类

Arrays
asList:将数组变成集合
把数组变成list集合的好处是什么
可以使用集合的思想和方法来操作数组中的元素,将数组变成集合  不可以使用集合的增删方法,因为数组的长度是固定的,如果增删了,那么会发生UnsupportedOperationException
集合变数组
Collection接口中的toArray方法
指定类型的数组到底要定义多长呢
当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组长度为集合的size
当指定类型的数组长度大于了集合的size,就不会新创建数组,而是使用传递进来的数组所以创建一个刚刚好的数组最优
为什么要集合变数组
为了限定对元素的操作,不需要进行增删了。
高级for循环
格式:

for(数据类型 变量名:被遍历的集合(Collection)或者数组){
}

 
对集合进行遍历
只能获取元素,但是不能对集合进行操作
迭代器:
除了遍历还可以进行remove集合中的元素的动作,如果使用ListIterator,还可以在遍历过程中对集合进行增删改查的动作
传统的for和高级的for有什么区别
高级for有局限性,必须有被遍历的目标。
建议在遍历数组的时候,还是希望使用传统for,因为传统for可以定义角标
可变参数
其实就是数组参数的简写形式,不用每一次都手动的建立数组对象,只要将要操作的元素作为参数传递即可,隐式将这些参数封装成了数组
在使用方法的可变参数时:
注意:
可变参数一定要定义在参数列表的最后面
当类名重名时,需要指定具体的包名
当方法重名时,指定具备所属的对象或者类
System
System类中的方法和属性都是静态的
out代表标准输出,默认是控制台dos
in是标准输入,默认键盘
描述系统的一些信息:
获取系统属性信息:getProperties
因为Properties是hashtable的子类,也就是map集合重的子类对象
可以通过map的方法取出该集合中的元素
该集合中存储的都是字符串,没有泛型定义
如何在系统中自定义系统信息呢?

System.setProperty("mykey","myValue");

获取所有属性信息

for(Object obj:prop.keySet()){
    String value = (String)prop.get(obj);
    System.out.println(obj+": "+value);
}

 
获取指定属性信息

String osName = System.getProperty("os.name");
System.out.println("os name ;"+osName);

 
 

Runtime对象

该类中并没有提供构造函数
说明不可以new对象,那么会直接想到该类中的方法都是静态的,发现该类中还有非静态方法,说明该类肯定会提供了方法获取本类对象,而且该方法是静态的,并返回值类型是本类类型
由这个特点可以看出该类使用了单例设计模式完成,保证了对象的唯一性
该方法是 static Runtime getRuntime()
Math
ceil    返回大于指定数据的最小整数
floor    返回小于指定数据的最大整数
round     返回指定数据四舍五入的值
IO流
字符流和字节流
字节流的两个基类:
InputStream    OutputStream
字符流的两个基类:
Reader        Writer
先学习一下字符流的特点
既然IO流是用来操作数据的,那么数据的最常见体现形式是:文件
那么先以操作文件为主来演示
需求:在硬盘上创建一个文件,并写入数据
找到一个专门用于操作文件的Writer子类对象,fileWriter。后缀名是父类名,前缀名是该流对象的功能
1.创建一个fileWriter对象,该对象一被初始化,就必须要明确被操作的文件
2.调用write方法,将数据写入流中
3.调用flush方法 刷新流对象中的缓冲中的数据
4.调用close方法,关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据
和flush的区别:
调用flush刷新后,流可以继续使用,但是close后,流将会关闭
IO异常的处理方式:

FileWriter fw =null;//!!!!!!!!!!!!!!!!!!
try {
    fw = new FileWriter("Demo.txt");
    fw.write("abcdefg");
}catch (IOException e){
    System.out.println(e.toString());
}finally {
    try {
    if(fw!=null)//!!!!!!!!!!!!!!!!!!!!!!!!
        fw.close();
} catch (IOException e) {
    System.out.println(e.toString());
  }
}

 
 

缓冲区

缓冲区的出现是为了提高流的操作效率而出现的
所以在创建缓冲区之前,必须要先有流对象
字符流缓冲区:
该缓冲区提供了一个一次读一行的方法 readLine,方便与对文本的数据获取,当返回null时,表示读到文件末尾
readLine方法返回的时候至返回回车符之前的内容,并不返回回车符
readLine方法的原理
无论是读一行,或者读取多少个字符,其实最终都是在硬盘上一个一个获取,所以最终使用的还是read方法一次读一个的方法。
装饰设计模式:
当想要对已有的对象进行功能增强时,
可以定义类,将已有对象传入,基于已有对象功能,并提供加强功能,那么自定义的该类成为装饰类。
装饰类通常会通过构造方法接收被装饰的对象
并基于被装饰的对象的功能提供更强的功能
MyReader//专门用于读取数据的类

|---MyTextReader
  |---MyBufferTextReader
|---MyMediaReader
  |---MyBufferMediaReader
|---MyDataReader
  |---MyBufferDataReader

装饰比继承更灵活,避免了继承体系臃肿
而且降低了类与类之间的关系。
装饰类:因为增强已有对象,具备的功能和已有对象是相同的,只不过提供了更强的功能所以装饰类和被装饰类都属于一个体系中的
想要操作图片数据,这时候就要用到字节流
复制一个图片
思路:
1.用字节读取流对象和图片关联
2.用字节写入流对象创建一个图片文件,用于存储获得到的图片数据
3.通过循环读写,完成数据的存储
4.关闭资源
通过键盘录入一行数据兵打印其大写,发现其实就是读一行数据的原理,也就是readLine方法,能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢
readLine方法是BufferedReader类中的方法
而键盘录入的read方法是字节流的InputSream的方法
那么能不能将字节流转成字符流再使用字符流缓冲区的readLine方法呢?

BufferedWriter bfw = new BufferedWriter(newOutputStreamWriter(System.out));//(System.in)

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

File类

File类常见方法
1.创建
boolean createNewFile();在指定位置创建文件,如果该文件已经存在则不创建,返回false和输出流不一样,输出流对象一建立就会创建文件,而且文件存在则会覆盖
static File createTempFile();  创建临时文件.temp
boolean mkdir();创建文件夹
boolean mkdirs();创建多级文件夹
2.删除
boolean delete();删除失败返回false
void deleteOnExit();在虚拟机退出的时候删除文件
3.判断
boolean canExecute();判断是否是可执行文件
boolean canRead();
boolean canWrite();
boolean exist();文件是否存在
boolean isFile();判断是否为文件
boolean isDirectory();判断是否为目录
boolean isHidden();判断是否为隐藏文件
4.获取信息
getName();获取名称
getPath();获取路径
getParent();获取父目录  //返回绝路径的父目录,如果获取的是相对路径,返回null
lastModifid();获取文件最后修改时间
length();获取文件大小
在windows中,删除目录是从最里面往外删除的。
既然是从里往外删除,就需要用到递归
propertoes 是hashTable的子类
也就是说他具备map集合的特点,而是它里面存储的键值对都是字符串,是集合中和IO技术相结合的容器
该对象的特点可以用于键值对形式的配置文件那么加载数据时,需要数据有固定格式,通常 键=值
dom4j
打印流:
该流提供了打印方法,可以将各种数据类型的数据都原样打印

字节输出流

PrintStream
构造函数可以接收的参数类型
1.file对象 file
2.字符串路径 String
3.字节输出流 OutputStream

字符输出流

PrintWriter
构造函数可以接收的参数类型
1.file对象 file
2.字符串路径 String
3.字节输出流 OutputStream
4.字符输出流 Writer
RandomAccessFile
该类不是IO体系中子类
而是直接继承自Object
但是,他是IO包中的成员,因为他具备读写功能,内部封装了,一个数组,而且通过指针对数组进行操作,可以通过GetFilePointer获取指针位置,同时可以通过seek改变指针的位置
其实完成读写的原理就是内部封装了字节输入流和输出流
通过构造函数可以看出,该类只能操作文件
而且操作文件还有模式 只读r 读写rw
如果模式为只读,不会创建文件,会去读取一个已存在的文件
如果该文件不存在,则会出现异常
如果模式为读写,那么要操作的文件不存在,会自动创建
如果存在,则不会覆盖
DataInputStream与DataOutputStream
可以用于操作基本数据类型的数据的流对象
用于操作字节数组的流对象
ByteArrayInputStream:
在构造的时候,需要接受数据源,而且数据源是一个字节数组
ByteArrayOutputStream:
在构造的时候,不用定义数据目的,因为该对象已经内部封装了可变长度的字节数组这就是数据目的地因为这两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭
在流操作规律讲解时:
源设备:键盘System.in 硬盘FileStream 内存 ArrayStream
目的设备:控制台System.out 硬盘FileStream 内存 ArrayStream
编码:字符串变成字节数组
解码:字节数组变成字符串
 
 

GUI图形用户界面

创建图形化界面
1.创建Frame窗体
2.对窗体进行基本设置,比如大小位置布局等
3.定义组建
4.将组件通过窗体的add方法添加到窗体中
5.让窗体显示,通过setVisable(true);
监听机制的特点:
1.事件源
2.事件
3.监听器
4.事件处理
事件源:就是awt包或者swing包中的那些图形界面组件
事件:没一个事件源都有自己特有的对应事件和共性事件
监听器:将可以触发某一个事件的动作(动作不止一个)都已经封装到了监听器中
以上三者,在java中都已经定义好了,直接获取其对象来用就可以了我们要做的事情,就是对产生的动作进行处理
 
 

网络编程

概述:(三要素 IP 端口 协议)
1.找到对方IP
2.数据要发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识,为了方便称呼这些数字,叫做 端口,逻辑端口
3.定义通讯规则,这个通讯规则成为 协议。国际组织定义了通用协议 TCP/IP
OSI(开放式系统互联    TCP/IP(网络通信协议)
应用层     |     应用层
表示层     |     ..
会话层   数据封包(数据拆包) ..
传输层     |     传输层
网络层     |     网际层
数据链路层   |     主机至网络层
物理层     V     ..
IP地址:
本地回环地址:127.0.0.1 主机名 localhost
端口:
0~65535  其中0~1024为系统保留端口
UDP:
将数据及源和目的封装成数据包中,不需要建立连接
每个数据包的大小限制在64k以内
因无连接,是不可靠协议
不需要建立连接,速度快
TCP:
建立连接,形成传输数据的通道
在连接中进行大数据量传输
通过三次握手完成连接,是可靠的协议
必须建立连接,效率会稍低
Socket:
Socket就是为网络服务提供的一种机制
通信的两端都有Socket
网络通信其实就是Socket间的通信
数据在两个Socket间通过IO传输
 
 

正则表达式(regex)

正则表达式:符合一定规则的表达式
作用:用于专门操作字符串
特点:用于一些特定的符号来表示一些代码操作,这样就简化书写
所以学习正则表达式就是在学习一些特殊符号的使用
好处:可以简化对字符串的复杂操作
弊端:符号定义越多,正则越长,阅读性越差
具体操作功能:
1.匹配: String matches方法  用规则匹配整个字符串,只要有一处
不符合规则就匹配结束,返回false
为了让规则结果可以被重用,可以将规则封装为一个组
用()完成,组的出现都有编号,从1开始,想要使用已有的组,可以用过
\n(组的编号)的形式来获取   (.)\1
2.切割: String split();
3.替换: String replaceAll();
4.获取: 将字符串中符合规格的子串取出
操作步骤:
1.先将正则表达式封装成对象
2.让正则对象和要操作的字符串相关联
3.关联后获取一个正则匹配引擎
4.通过引擎对符合规则的子串进行操作,比如取出
如果只想知道该字符是否对错: 匹配
想要按照自定义的方式将字符串变成多个字符串:切割
如果想要将已有的字符串变成另一个字符串:替换
想要拿到符合需求的字符串子串:获取

分类: JAVA SE

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注