一.Java类及类的成员
1.属性 = 成员变量 = field = 域,字段
属性赋值的先后顺序:①默认初始化②显式初始化③构造器中赋值④通过”对象.方法“或”对象.属性“的方式,赋值。
2.方法 = 成员方法 = 函数 = method
3.构造器:
3.1作用:①创建对象②初始化对象的属性
3.2若没有显示的定义类的构造器的话,则系统默认提供一个空参的构造器
3.3定义的构造器的格式:权限修饰符 类名(形参列表){ }
3.4一旦我们显示的定义了类的构造器之后,系统就不再提供默认的空参构造器
3.5一个类内部可以有输出语句中,至少会有一个构造器。
***javaBean是一种Java语言写成的可重用组件①类是公共的②有一个无参的公共的构造器③有属性,且有对应的get,set方法
4.代码块:{ } 可以用static来修饰 作用:用来初始化类,对象
分类:静态代码块 vs 非静态代码块(静态代码块先于非静态代码块执行)
静态代码块:内部可以有输出语句。随着类的加载而执行,只执行一次。作用:初始化类的信 息。如果一个类中定义了多个静态代码块,则按照声明的先后顺序来执行。*静态 代码块内只能调用静态的属性方法,不能调用非静态的结构。
非静态代码块:内部可以有输出语句。*随着对象的创建而执行,每创建一个对象,就执行 一次非静态代码块。*作用:可以在创建对象时,对对象的属性等进行初始化。*如果一个类 中定义了多个非静态代码块,则按照声明的先后顺序来执行。*可以调用静态,非静态的属 性,方法
5.内部类:
5.1.Java中允许选择一个类A声明再另一个类B中,则类A就是内部类,类B称为外部类。
5.2内部类的分类:成员内部类(静态,非静态) vs 局部内部类(方法内,代码块内,构造器内)。
5.3成员内部类:
一方面,作为内部类的成员:调用外部类的结构;可以被static修饰;可以被4种权限修饰。
另一方面,作为一个类:类内可以定义属性,方法,构造器;可以被final修饰,表示此类不能被继承,因此不使用final就可以被继承;可以被abstract修饰。
二.类和对象的使用(面向对象落地的实现)
1.创建类,设计类的成员
2.创建类的对象
3.通过”对象.属性“或”对象.方法“调用对象的结构。
三.面向对象的俩要素
类:抽象概念上的定义
对象:实际存在的该类事物的每个个体,实例(instance)
创建类的对象 = 类的实例化 = 实例化类
四.类中属性的使用
属性(成员变量) vs 局部变量
1.相同点
1.1格式相同
1.2先声明,后使用
1.3变量都有其对应的作用域
2.不同点
2.1位置不同
属性:直接定义在类的一堆{}内。
局部变量:声明在方法内,方法形参,代码块内,构造器形参,构造器内部的变量
2.2权限修饰符不同
属性:可以在声明属性时,指明其权限,使用权限修饰符。
常用的权限修饰符:private,public,缺省,protected
局部变量:不可以使用权限修饰符
2.3默认初始化值的情况
属性:类的属性,根据其类型,都有默认初始化值。
局部变量:没有默认初始化值,因此调用局部变量之前,必须显示赋值。
特别的:形参在调用时,赋值即可。
2.4在内存中加载的位置不同
属性:加载到堆空间(非static)
局部变量:加载到栈空间
五.方法
1.方法的使用中,可以调用当前类的属性或方法
特殊的:方法A中又调用了方法A:递归方法。
方法中不可以定义方法。
***方法的重载:俩同一不同。相同点:方法名相同和同一个类;不同点:参数列表不同(参数个数不同,参数类型不同)。跟方法的权限修饰符,返回值类型,形参变量名,方法体都没有关系。因此当对象调用方法时,①看方法名②看参数列表
***可变个数形参①格式,数据类型 ...变量名②调用可变个数形参时,传入参数可以是0,1,2...
③可变个数形参与本类中方法名相同,形参个数不同的构成重载。④可变个数形参与本类中方法名相同,形参类型也相同的数组之间不构成重载。⑤可变个数形参必须在末尾⑥最多只能声明一个形参。
***变量的赋值①基本数据类型,赋值的是变量所保存的数据值。②引用数据类型,赋值的是变量所保存的地址值。
2.方法的形参的传递机制:值传递机制
2.1.形参:方法定义时,小括号内的参数;实参:对象调用方法时,实际传递给形参的数据。
2.2.值传递机制:如果参数是基本数据类型,那么实参赋给形参的是真实的数据值 ;如果参数是引用数据类型,那么实参赋给形参的是实参存储数据的地址值。
3.toString方法
3.1.当我们输出一个对象的引用时,实际上就是调用当前对象的toString()
3.2.像String,Date,File,包装类等都重写了Object类中的toString()方法。使得在调用对象的toString()时,返回“实体内容”信息
3.3自定义类可以重写toString()方法,当调用此方法时,返回对象的“实体内容”。
六.面向对象三大特性
1.1封装性:我们将类的属性(xxx)私有化,同时提供公共(public)的方法来获取(getXxx)和设置(setXxx)
拓展:封装性的体现:①同上②不对外暴露私有的方法③单例模式
1.2封装性的体现,需要权限修饰符来配合
①java规定的4种权限(从小到大排列):private,缺省,protected,public
②4种权限可以用来修饰类及类的内部结构:属性,方法,构造器,内部类
③修饰类的话,只能使用:缺省,public。
1.3总结:Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用 时 的可见性的大小。
2.1继承性优点:①减少冗余②便于功能的扩展③为之后的多态性的使用,提供了前提
2.2格式:class A extends B{ }
A:子类,派生类,subclass
B:父类,超类,基类,superclass
体现,一旦子类A继承父类B之后,子类就获取了父类声明的结构属性方法
***特别的,父类中声明为private的属性或方法,子类继承父类后,仍获取了,只因为封装性,使 得子类不能直接调用父类的结构
2.3规定:①一个类可以被多个子类继承②一个类只能有一个父类,Java中类的单继承性。
③子类继承父类后,继承了直接父类和间接父类声明的结构
***方法的重写(子类中叫重写的方法,父类中叫被重写的方法)①子类继承父类后,可以对父类 同名同参数的方法,进行覆盖操作
②重写以后,当创建子类对象后,通过子类对象调用此方法时,执行的是重写后的方法。
***重写的规定:①子类重写的方法名和参数列表相同②子类重写的权限修饰符不小于父类被重写 的方法的权限修饰符,特殊情况:子类不能重写父类中声明为private权限的方法
③返回值类型:父类被重写的方法名和形参列表是void,子类只能是void;父类是A类型,子类 返回值类型可以是A类型或A类的子类;父类返回值类型是基本数据类型,则子类也必须是相同 的基本数据类型。
④子类重写的方法抛出的异常类型不大于父类被重写的方法被掏出的异常类型。⑤子类和父类同 名同参数的方法都生声明为非static的才考虑重写。
3.1多态性:一个事物的多种形态
3.2对象的多态性,父类的引用指向子类的对象(或子类的对象赋给父类的引用)
3.3多态性的使用,虚拟方法调用--有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。总结:编译看左边,运行看右边。
3.4多态性的使用前提:①类的继承关系②方法的重写
3.5对象的多态性:只适用于方法,不适用于属性。
***向上转型即为多态。
***向下转型,使用强制类型转换符。使用强转时,可能出现异常,因此使用instanceof进行判断
七.关键字
1.this关键字①this可以用来修饰:属性,方法,构造器
②this修饰属性和方法,this理解为:当前对象。属性与形参同名时,使用“this.变量”表明此变量是属性,而非形参。
③在类的构造器中,可以显示的使用”this(形参列表)“方式,调用本类中指定的其他构造器;构造器中不能通过此方式调用自己;如果一个类中有n个构造器,最多有n-1个此方式;此方式必须声明在当前构造器中的首行;构造器的内部:最多只能声明一个此方式
2.package关键字①为了更好的实现项目中类的管理
②使用package声明类或接口所属的包,声明在源文件的首行
③包,属于标识符,遵循标识符的命名规则(xxxyyyzzz),"见名知意"
④每”.“一次就代表一层文件目录
3.import关键字的使用:导入
①显示使用import结构导入指定包下的类,接口②声明在包的声明和类的声明之间
③需要多个结构,并列写出④可以使用”xxx.*“的方式,表示可以导入xxx包下的所有结构;若使用xxx子包下的结构,则仍需要显示
⑤如果使用的类或接口是Java.lang包下定义的,则可以省略import结构
⑥使用不同包下同名的类,则必须至少有一个类需要以全类名的方式显示
4.super关键字的使用:
①理解为父类的②可以用来调用属性,方法,构造器
③super.属性或super.方法的方式,显示的调用父类的属性或方法;子父类定义了同名的属性
时, 在子类中调用父类中声明的属性,则必须显示的使用”super.属性“的方式,表明调用的是父 类中声明的属性;子类重写了父类的方法时,则必须显示使用”super.方法“的方式,调用的是父 类中被重写的方法。
④4.1在子类的构造器中显示的使用”super(形参列表)“的方式,请用父类中声明的指定的构造器
4.2”super(形参列表)“的使用,必须声明在子类的构造器的首行
4.3在类的构造器中,this(形参列表)或super(形参列表)只能二选一,不能同时出现
4.4在构造器的首行没有显示声明,那么默认调用父类的空参的构造器
4.5在类的多个构造器中,至少有一个构造器中使用了”super(形参列表)“,调用父类中的构造器
5.instanceof关键字的使用
5.1a instanceof A:判断对象a是否是类A的实例。如果是返回true,如果不是返回false。
5.2a instanceof A返回true,类B是类A的父类,则a instanceof B也返回true。
6.static关键字的使用:静态的
6.1:可以修饰属性,方法,代码块,内部类。
6.2修饰属性:静态变量(类变量)
按是否使用static修饰,又分为:静态属性 vs 非静态属性(实例变量)
实例变量:创造了类的多个对象,每个对象都独立的拥有一个类中的非静态属性,当修改其 中一个对象的非静态属性时,不会影响其他对象同样的属性值的修改。
静态变量:我们创造了多个对象,共享一个静态变量,当通过某一个对象修改静态变量时, 会导致其他对象调用此静态变量时,是修改了的。
6.3 static 修饰属性的说明:
①静态变量随着类的加载而加载,可以通过“类.静态变量”的方式进行调用
②静态变量的加载要早于对象的创建
③类只加载一次,所以静态变量在内存中也只有一份,在方法区的静态域中
6.4static 修饰方法的说明:
①随着类的加载而加载,可以通过“类.静态方法”的方式进行调用
②静态方法中,只能调用静态的方法和属性;非静态方法中,既能调用非静态的方法和 属性,也能调用静态的方法和属性。
6.5 开发中,如何确定一个属性是否要声明为static?
> 属性可以被多个对象所共享的,不会随着对象的不同而不同的。
开发中,如何确定一个方法是否要声明为static?
> 操作静态属性的方法,习惯上声明为static的。比如:Math,Arrays,Collections。
7.final:最终的
7.1:final可以修饰类,方法,变量
7.2final 用来修饰一个类:此类不能被其他类所继承。
比如:String类,System类,StringBuffer类。
7.3final 用来修饰方法:此方法不能被重写。
比如:Object类中getClass( );
7.4 final 用来修饰变量,此时的“变量”就称为是一个常量。
final修饰属性,可以考虑赋值的位置有:显式初始化,代码块中初始化,构造器中初始化
final修饰局部变量:使用final修饰形参时,表明形参是一个常量,当我们调用此方法时, 给常量赋一个实参,赋值后就只能在方法体内使用此形参,但不能进行重新赋值。
7.5 static final 修饰属性:全局常量。
8.abstract 关键字:抽象的
8.1 abstract 可以用来修饰的结构:类,方法
8.2 abstract 修饰类:抽象类
①此类不能实例化 ②抽象类中一定有构造器,便于子类实例化时调用(涉及:子类对 象实例化的全过程)③开发中,都会提供抽象类的子类,子类对象实例化。
8.3 abstract 修饰方法,抽象方法
①抽象方法只有方法的声明,没有方法体②包含抽象方法的类,一定是一个抽象类。反 之,抽象类可以没有抽象方法。③若子类重写了父类所有的抽象方法后,此子类可以 实例化;若子类没有重写父类中所有的抽象方法,则此子类也是一个抽象类。
注意:abstract 不能用来修饰,属性,构造器等结构;abstract 不能用来修饰私有方 法,静态方法,final 的方法,final 的类。
八.调试程序
1.调式方法①syso()②Eclipse - Debug 调试
2.Java中的JUnit单元测试
步骤:①选中当前工程 - 右键选择:build path - add libraries - JUnit 4 - 下一步。②创建Java类,进行单元测试。此时的Java类要求,此类是public,没有返回值,没有形参③此类中声明单元测试方法,此时的权限是public,没有返回值,没有形参④此单元测试方法上需要声明注释:@Test,并在单元测试类中导入:import org.junit.Test。⑤声明好单元测试方法以后,就可以在方法体内测试相关的代码。⑥写完代码以后,左键双击单元测试方法名,右键:run as - JUnit Test。⑦若没有异常,绿条;若异常,红条。
九.包装类
1.Java提供了8种基本数据类型对应的包装类,使得基本数据类型的变量具有类的特征。
2.包装类 - ->基本数据类型:调用包装类Xxx的xxxValue()
基本数据类型 - ->包装类:调用包装类的构造器
String类型--->基本数据类型,包装类,调用包装类的parseXxx(String s)
基本数据类型,包装类--->String类型,调用String重载的valueOf(Xxx xxx)
十.单例设计模式
1.单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象 实例。
2.懒汉式 vs 饿汉式
3.区分饿汉式和懒汉式
饿汉式:坏处:对象加载时间过长。好处:饿汉式是线程安全的。
懒汉式:好处:延迟对象的创建。坏处:目前的写法,线程不安全--->到多线程内容时再修改。
十一.接口,内部类
1.成员内部类和局部内部类,在编译以后,都会生成字节码文件。
格式:成员内部类:外部类$内部类名:class
局部内部类:外部类$数字 内部类名:class
2.在局部内部类的方法中,如果调用局部内部类所声明的方法中的局部变量,要求此局部变量声明为final的。jdk7以前需要显示声明final的,jdk8以后可以省略final。
十二.异常
1.Error:Java虚拟机无法解决的严重问题。比如:堆溢出,栈溢出。
2.Exception:因编程错误导致的一般性问题,可以使用针对性处理。
例如:空指针访问,试图读取不存在的文件,网络连接中断,数组角标越界。
3.异常分位编译时异常和运行时异常
运行时异常:NullPointerException(空指针异常),IndexOutofBoundsException(角标越界异常),ClassCastException(类型转换异常),InputMisatchException(输入不匹配异常)
4.异常时处理:抓抛模型
过程一:“抛”:程序在正常执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异常的对象,并将此对象抛出,一旦抛出对象以后,其后的代码就不再执行。
关于异常对象的产生:①系统自动生成的异常对象②手动的生成一个异常对象,并抛出(throw)。
过程二:“抓”,可以理解为异常的处理方式:①try-catch-finally ②throws
方法一:
说明:1.finally 是可选的。2.使用try 将可能出现异常代码包装起来,在执行的过程中,一旦出现异常,就会生成一个对应异常类的对象,根据此对象的类型,去catch中进行匹配。3.一旦try中的异常对象匹配到一个catch时,就会进入catch中进行异常的处理,处理完成,跳出当前结构。4.catch中的异常类型如果具有满足子父类关系,则要求子类一定声明在父类的上面,否则,报错。5.常用的异常对象处理的方式:①String getMessage() ②printStackTrace() 6.在try结构中声明的变量,再出了try结构以后,就不能再被调用。7.try-catch-finally 结构可以嵌套。
5.finally:是可选的;finally中声明的是一定会被执行的代码,那使catch中又出现异常了,try中有return语句等情况;像数据库连接,输入输出流,网络编程Socket等资源,JVM是不能自动的回收的,我们需要手动的进行资源的释放,此时的资源释放,就需要声明在finally中。
方法二:
1. "throws + 异常类型"写在方法的声明处,指明此方法执行时,可能会抛出的异常类型。一旦出现方法体执行时出现异常,仍会在异常代码处生成一个异常类的对象,此对象满足throws后异常类型时,就会被抛出,异常代码后续的代码,就不再执行。
2. 理解:try-catch-finally:真正的将异常处理了;throws的方式只是将异常抛给了该方法的调用者,并没有真正的将异常处理掉。
3.开发中如何选择:
①如果父类中被重写的方法没有throws方式处理异常,则子类重写的方法也不能使用throws,
意味着如果子类重写的方法有异常,必须使用try-catch-finally方式处理。
②执行的方法a中,先后又调用了另外几个方法,这几个方法是递进关系执行的。我们建议这几个方法使用throws的方式进行处理。而执行的方法a可以考虑使用try-catch-finally方式进行处理。
如何自定义异常类:
1.继承于现有的异常结构:RuntimeException,Exception
2.提供全局常量:serialVersionUID
3.提供重载的构造器
十三.多线程
1. 测试Thread中的常用方法
1.1.start():启动当前线程,调用当前线程的run()
1.2.run():通常需要重写Thread类中的此方法,将创建的线程要执行的操作声明在此方法中
1.3.currentThread():静态方法,返回执行当前代码的线程
1.4.getName:获取当前线程的名字
1.5.setName():设置当前线程的名字
1.6.yield():释放当前cpu的执行权
1.7.join():在线程a中调用线程b的join(),此时线程a就进入阻塞状态,直到线程b完全执行完以后,线程a才结束阻塞状态
1.8.stop():已过时。在执行此方法时,强制结束当前线程
1.9.sleep(Long millitime):让当前线程“睡眠”指定的millitime毫秒,在指定millitime毫秒时间内,当前线程是阻塞状态
1.10.isAlive():判断当前线程是否存活
2.线程的优先级
2.1. MAX_PRIORITY 10
MIN_PRIORITY 1
NORM_PRIORITY 5
2.2.如何获取和设置当前线程的优先级:getPriority():获取线程的优先级;setPriority():设置线程的优先级。
说明:高优先级的线程要抢占低优先级的线程cpu的执行权,但是只是从概率上讲,高优先级的线程高概率的情况下被执行,并不意味着只有高优先级的线程执行完以后,优先级低的线程才执行。
3.创建多线程的方式一:继承Thread 类
①创建一个继承于Thread类的子类②重写Thread类的run() ---> 将此线程执行的操作声明在run()中③创建Thread类的子类的对象④通过此对象调用start()
创建多线程的方式二:实现Runnable接口
①创建一个实现Runnable 接口的类 ②实现类去实现Runnable 中的抽象方法:run() ③创建实现类的对象 ④将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象 ⑤通过Thread类的对象调用start()。
俩种方式的比较:①开发中,实现Runnable接口的方式②原因:*实现的方式没有类的单继承性的局限性 *实现的方式更适合来处理多个线程有共享数据的情况③联系:Thread类实现了Runnable()方法④相同点:俩种方式都需要重写Run(),将线程要执行的逻辑声明在Run()中。
方式三(JDK5.0新增):实现Callable接口:①创建一个实现Callable接口的实现类②实现call方法,将此线程需要执行的操作声明在call中③创建Callable接口实现类的对象④将Callable接口实现类的对象作为传递到FutureTask的构造器中,创建FutureTask的对象⑤将FutureTask的对象作为参数传递到Therad类的构造器中,创建Thread对象,并调用start()⑥获取Callable中的call方法的返回值
实现Callable接口的方式创建多线程比实现Runnable接口创建多线程方式优点:①call方法可以有返回值②call方法可以抛出异常,被外面的操作捕获,获取异常的信息③Callable是支持泛型的
方式四:使用线程池:①提供指定线程数量的线程池②执行指定现场的操作,需要提供实现Runnable接口或Callable接口实现类的对象③关闭连接池
优点:①提高响应速度②降低资源消耗③便于线程管理
3.线程的安全问题
3.1.我们可以通过同步机制,求解决线程的安全问题
方法一:同步代码块,synchronized(同步监视器){ // 需要被同步的代码 }
说明:①操作共享数据的代码,即为需要被同步的代码②共享数据,多个线程共同操作的变量③同步监视器,俗称:锁,如何一个类的对象,都可以充当锁。要求:多个线程必须要公用同一把锁。
补充:①在实现Runnable接口创建多线程的方式中,我们可以考虑使用this充当同步监视器。②在继承Thread类创建多线程的方式中,慎用this充当同步监视器,考虑使用当前类充当同步监视器。
方法二:同步方法
总结:①同步方法涉及到同步监视器,只是不需要我们显示的声明②非静态的同步方法,同步监视器是:this;非静态的同步方法,同步监视器是,当前类本身。
方法三:Lock锁 --- JDK5.0新增
需要手动启动同步(Lock()),同时结束同步也需要手动的实现(unLock())
4.线程通信
4.1涉及到的三个方法:wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。 notify():一旦执行此方法,就会唤醒被wait的一个线程。 notifyAll():一旦执行此方法,就会唤醒所有被wait的线程。
说明:①三个方法只能出现在同步代码块和同步方法中 ②这三个方法的调用者必须是同步代码块或同步方法中的同步监视器,否则会出现异常。
sleep()和 wait ()的异同:
1)相同点:一旦执行方法,都可以使当前线程进入阻塞状态。
2)不同点:①俩个方法声明的位置不同:Thread类中声明sleep(),Object类中声明wait();②调用的要求不同:sleep()可以在任何需要的场景下调用,wait()必须使用同步代码块和同步方法下调用③关于是否释放同步监视器:如果俩个方法都使用同步代码块和同步监视器,sleep()不会释放锁,wait()会释放锁。
十四.Java常用类
1.String:字符串,使用一对" " 引起来表示。
2.String实现了Serializable接口:表示字符串是支持序列化的。 实现了Comparable接口:表示String可以比较大小。
3.String内部定义了final char[ ] value用于存储字符串数据
4.String:代表了不可变的字符序列。简称:不可变性。
体现:①当对字符串重新赋值时,需要重新指定内存区域赋值,不能使用原有的value进行赋值。②当对现有的字符使用连接操作时,需要重写指定内存区域赋值,不能使用原有的value进行赋值,需要重新指定内存区域进行赋值③当调用String的replace()方法修改指定字符或字符串时,不能使用原有的value进行赋值,也需要重新指定内存区域进行赋值。
5.通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
6.字符串常量池中是不会存储相同内容的字符串中。
7.常量与常量的拼接结果在常量池,且常量池中不会存在相同内容的常量。
8.只要其中有一个时变量,结果就在堆空间中。
9.如果拼接的结果调用intern()方法,返回值就在常量池中。
10.String --> char[]:调用String的toCharArray()方法;
char[] --> String:调用String的构造器。
编码:String --> byte[ ] : 调用String的getBytes( ) 编码:字符串 --> 字节
解码:byte[ ] --> String :调用String的构造器 解码:字节 --> 字符串
说明:解码时,要求解码使用的字符集一致,否则会出现乱码。
11.String:不可变的字符序列,底层使用的时char[ ]存储;StringBuffer:可变的字符序列,线程安全的,效率低,底层使用char [ ]存储;StringBuilder:可变的字符序列,jik5.0新增,线程不安全,效率高,底层使用char[ ] 存储。
StringBuffer:①底层创建了一个长度为16的char型数组。②扩容问题:如果要添加的数据底层数组盛不下了,那就需要扩容底层的数组。
建议使用:StringBuffer(int capacity) 或 StringBuffer(int capacity)
效率从高到底排列:StringBuilder > StringBuffer > String
12.java.util.Data类
①构造器的使用:构造器一:Data():创建一个对应当前时间的Data对象;构造器二:创建指定毫秒数的Data对象。
②俩个方法的使用:toString( ):显示当前的年月日时分秒;getTime( ):获取当前Data对象对应的毫秒数。(时间戳)
③java.sql.Data 对应着数据库中的时期类型的变量
13.SimpleDateFormat 类是一个允许进行
①格式化:日期 --> 文本 格式化:调构造器
②解析:文本 --> 日期 解析:调parse方法
14.Calendar
①实例化:方式一:创建其子类(GregorianCalendar)的对象。 方式二:调用其静态方法getInstance()。
②常用方法:get,set,add, getTime:日历类 ---> Date ,setTime():Date ---> 日历类
15.jdk8之后
LocalDate,LocalTime,LocalDateTime 的使用:①now()获取当前的日期,时间,日期+时间②of():设置指定的年,月,日,时,分,秒,没有偏移量。③getXxx()④withXxx():体现了不可变性⑤plusXxx加。⑥minus:减。
新日期API:①now() :静态方法,返回默认UTC时区的instant类的对象。②ofEpochMill(long offset):静态方法,返回在1970-01-01 0点0分0秒基础上加上指定毫秒数之后的instant类的对象。③atOffset(ZoneOffset offset):结合即时的偏移来创建一个OffsetDateTime。④toEpochMill():返回1970-01-01 0点0分0秒到当前的毫秒数,即为时间戳。
DateTimeFormatter类:该类提供了三种格式化方法:①ofPattern(String pattern):静态方法,返回一个指定字符串格式的DateTimeFormatter②format(TemporatAccessor t):格式化一个日期,时间,返回字符串③parse(CharSequence text):将指定格式的字符串序列解析为一个日期,时间
16.Comparable接口的使用:保证Comparable接口实现类的对象在任何位置都可以比较大小。Comparator接口属于临时性的比较。
①像String,包装类等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较俩个对象的方法②像String,包装类重写compareTo()方法以后,进行了从小到大的排列③重写compareTo(obj)的规则:this大于形参对象obj,返回正整数;小于返回负整数;等于返回0。
十四.枚举类
1.枚举类的使用:1.1类的对象只有有限个,确定的。
1.2.当定义一组常量时,建议使用枚举类。
1.3.如果枚举类中只有一个对象时,则可以作为一种单例模式的实现方式。
2.如何定义一种枚举类:
2.1 JDK5.0之前,自定义枚举类
2.2 JDK5.0之后,使用enum定义枚举类:定义的枚举类默认继承于java.long.Enum类
十五.注解
1.Annotation的使用示例
示例一:生成文档相关的注解
示例二:在编译时进行格式检查(JDK内置的三个基本注解):①@Override:限定重写父类方法,该注解只能用于方法②@Deprecated:用于表示所修饰的元素(类,方法)已过时③@SuppressWarnings:抑制编译器警告
示例三:跟踪代码依赖性,实现替代配置文件功能
2.自定义注解:参照 @SuppressWarnings 定义:①注解声明为:@interface ②内部定义成员,通常使用value表示 ③可以指定成员的默认值,使用default定义④如果自定义注解没有成员,表明时一个标识作用⑤如果注解有成员,在使用注解时,需要指明成员的值。⑥自定义注解必须配上注解的信息处理流程(使用反射)才有意义。
3. jdk提供的4种元注解:对现在的注解进行解释说明的注解
Retention:指定修饰的 Annotation 的生命周期:SOURCE\CLASS(默认行为)\RUNTIME 只有声明为RUNTIME 生命周期的注解,才能通过反射获取。
Target:用于指定被修饰的Annotation 能用于修饰哪些程序元素。
Documented:表示所修饰的注解在被Javadoc解析时,保留下来。
Inherited:被它修饰的 Annotation 将具有继承性。
4. 新特性:可重复注解,类型注解
可重复注解:①在MyAnnotation 上声明@Repeatable,成员值为MyAnnotations,class。②MyAnnotation的Target 和 Retention 和 MyAnnotations 相同。
类型注解:①ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中。②ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中。
十六.集合框架的概述
1. 集合,数组都是对多个数据进行存储操作的结构,简称Java容器。
说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库中)
2. 数组在存储多个数据方面的特点:一旦初始化,长度就确定;需要指明数组的具体类型,一旦定义好,元素类型就确定了,只能操作指定类型的数据。
缺点:长度不可被改变;数组中提供的方法非常有限,对于添加,删除,插入数据等操作,非常不便。同时效率不高;获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用;数组存储数据的特点:有序,可重复,对于无序不可重复的需求,不能满足。
3.集合框架
3.1. Collection接口:单列集合,用来存储一个一个的对象
List接口:存储有序的,可重复的数据 --> “动态”数组
ArrayList,LinkedList,Vector
相同点:三个类都是实现了List接口,存储数据的特点相同,存储有序的,可重复的数据。
不同点:ArrayList:作为List的主要实现类,线程不安全,效率;底层使用Object[] elementData存储; JDK7情况下:底层创建了长度是10的Object[] 数组elementData。List.add:如果此次的添加导致底层elementData数组容量不够,则扩容,默认情况下,扩容为原来容量的1.5倍,同时需要将原来数组中的数组复制到新的数组中。结论:建议使用带参的构造器 JDK8情况下:底层Object[] 数组elementData初始化为{ },并没有创建长度
总结:常用方法:增:add(Object obj);删:remove(int index)/remove(Object obj);改:set(int index,Object obj);查:get(int index);插:add(int index,Object obj);长度:size();遍历:①Iterator迭代器方式②增强for循环;
LinkedList:对于频繁的插入,删除操作,使用此类效率比ArrayList高:底层使用双向链表 Vector:作为List的古老实现类,线程安全,效率低;底层使用Object[] elementData存储
Set接口:存储无序的,不可重复的数据
HashSet:作为Set接口的主要实现类,线程不安全的,可以存储null值;LinkedHashSet:作为HashSet的子类,遍历其内部数据时,可以按照添加的顺序遍历;TreeSet:可以按照添加对象的指定属性,进行排序。
3.2.Map接口:双列集合,用来存储一对(key - value)一对的数据。
HashMap:作为Map的主要实现类,线程不安全,效率高;存储null的key和value-->LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历。
TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然底层使用红黑树。
Hashtable:作为古老的实现类,线程安全,效率低;不能存null的key和value-->Properties:常用来处理配置文件,key和value都是String类型
HashMap的底层:数组+链表(jdk7及之前) 数组+链表+红黑树(jdk 8)
十七.泛型.
1.总结:①集合接口或集合类在jdk5.0时都修改为带泛型的结构②在实例化集合类时,可以指明具体的泛型类型③指明完以后,在集合类或接口中凡是定义类或接口时,内部结构使用到类的泛型的位置,都指定为实例化的泛型类型。④注意点:泛型的类型必须是类,不能是基本数据类型⑤如果实例化时,没有指明泛型的类型,默认类型为object类型
2.自定义泛型结构:泛型类,泛型接口,泛型方法
泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。泛型方法所属的类是不是泛型都没有关系。泛型方法可以声明为静态的。原因:泛型参数是在调用方法时确定的。并非在实例化类时确定的。
3.泛型在继承方面的体现:虽然类A是类B的父类,但是G<A> 和 G<B>二者不具备子父类关系,二者是并列关系。补充:类A是类B的父类,A<G> 是 B<G> 的父类。
通配符:? 类A是类B的父类,G<A> 和 G<B>是没有关系的,二者共同的父类是:G<?> 对于List<?> 就不能向其内部添加数据。除了添加null之外。
获取:允许读取数据,读取的数据类型为object。
十八.IO流
1.File类的一个对象,代表一个文件或一个文件目录(俗称:文件夹)
2.File类声明在Java.io包下
3.相对路径:相对于某个路径下,指明的路径。 绝对路径:包含盘符在内的文件或文件目录的路径。
4.public String[] List():获取指定目录下的所有文件或者文件目录的名称数组
public File ListFiles():获取指定目录下的所有文件或者文件目录的File数组
public boolean renameTo(File dest):把文件重命名为指定的文件路径
5.File类中涉及到关于文件或文件目录的创建,删除,重命名,修改时间,文件大小等方法,并未涉及到写入或读取文件内容的操作,如果需要读取或写入文件内容,必须使用IO流来完成
6.后续File类的对象常会作为参数传递到流的构造器中,指明读取或写入的“终点”。
7.流的分类:①流的数据单位:字节流,字符流 ②流向:输入流,输出流 ③角色:节点流,处理流
8.流的体系结构:抽象基类:InputStream,OutputStream,Reader,Writer
节点流(或文件流):FileInputStream,FileOutputStream,FileReader,FileWriter 缓冲流(处理流的一种)BufferedInputStram,BufferedOutputStream,BufferedReader,BufferedWriter
9.read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1。
10.异常的处理:为了保证资源一定可以执行关闭操作,需要使用try-catch-finally 处理
11.读入的文件一定要存在,否则就会报FileNotFoundException。
12.输出操作,对应的File可以不存在的;如果不存在,在输出的过程中,会自动创建此文件;如果存在:如果流使用的构造器是:FileWriter(file,false)/FileWriter(file):对原有文件的覆盖,如果流使用的构造器是:FileWriter(file,true)就不会对原有文件覆盖,而是在原有文件后追加
13.不能使用字符流来处理图片等字节数据;文本文件(.txt,.java,.c,.cpp),使用字符流处理;非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt),使用字节流处理。
14.资源关闭:先关闭外层的流,再关闭内层的流。关闭外层流的同时,内层流也会关闭。关于内层流的关闭,我们可以省略。
15.转换流:属于字符流 InputStreamReader:将一个字节的输入流转换成字符的输出流 OutputStreamWriter:将一个字符的输出流转换为字节的输出流 作用:提供字节流与字符流之间的转换
16.数据流:DataInputStream 和 DataOutputStream:作用用于读取或写出基本数据类型的变量或字符串