Java笔记

软件开发介绍
1.常用的DOS命令
“D:”:切换盘符
dir:列出当前目录下的文件以及文件夹
md :创建目录
rd :删除目录
cd :进入指定目录
cd.. :退回到上一级目录
cd\ :退回到根目录
del :删除文件
exit:退出 dos 命令行
补充:echo javase>1.doc,echo javase>>1.doc

2.Java技术体系平台
Java SE(Java Standard Edition)标准版
Java EE(Java Enterprise Edition)企业版
Java ME(Java Micro Edition)小型版

3.Java主要特性
易学,强制面向对象,健壮,安全,体系结构中立,解释型,性能略高,原生支持多线程,跨平台

4.Java的两种核心机制
Java虚拟机
垃圾收集机制

5.配置环境变量
配置方法:
我的电脑--属性--高级系统设置--环境变量
编辑 path 环境变量,在变量值开始处加上java工具所在目录,后面用 “ ; ”和其他值分隔开即可。
打开DOS命令行,任意目录下敲入javac。如果出现javac 的参数信息,配置成功。

6.如何编译?
将 Java 代码编写到扩展名为 .java 的文件中。
通过 javac 命令对该 java 文件进行编译。
通过 java 命令对生成的 class 文件进行运行。

7.Java注释:用于注解说明解释程序的文字就是注释。
单行注释//
多行注释/* /
文本注释/
*

作用:
提高了代码的阅读性;调试程序的重要方法。
注释是一个程序员必须要具有的良好编程习惯。
将自己的思想通过注释先整理出来,再用代码去体现
对于单行和多行注释,被注释的文字,不会被JVM(java虚拟机)解释执行。
多行注释里面不允许有多行注释嵌套。

小结:
Java源文件以“java”为扩展名。源文件的基本组成部分是类(class),如本例中的HelloWorld类。
Java应用程序的执行入口是main()方法。它有固定的书写格式:
public static void main(String[] args) {...}
Java语言严格区分大小写。
Java方法由一条条语句构成,每个语句以“;”结束。
大括号都是成对出现的,缺一不可。
一个源文件中最多只能有一个public类。其它类的个数不限,如果源文件包含 一个public类,则文件名必须按该类名命名。

8.Java语言规定标识符由字母、下划线、美元符号和数字组成,并且第一个字符不能是数字。

9.Java中整型变量有byte、short、int和long四种,不同类型的整数变量在内存中分配的字节数不同,数值范围也不同。
对于byte型变量,内存分配1个字节,一个字节=8bit,bit: 计算机中的最小存储单位。byte:计算机中基本存储单元。
对于int型变量,内存分配4个字节。
在Java中浮点型变量有float和double两种,
对于float型变量,内存分配4个字节,尾数可精确到7位有效数字,
对于double型变量,内存分配8个字节。

基本数据类型:整数型:byte,short,int,long;浮点型:float,double;字符型:char;布尔型:Boolean;
引用数据类型:类、接口类型、数组类型、枚举类型、注解类型,字符串型

12.原码、反码、补码含义、作用及其转换
1.原码:一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小
在计算机中运算时会产生两个整数相加为负数的现象,因此在计算机存储中不会采用原码形式。
2、反码:数值位就是真值的绝对值,符号位位“0”时表示正数,符号位为“1”时表示负数,原码又称带符号的绝对值。为了方便整数和小数区别,整数的符号位与数值位之间用“,”隔开,小数的符号位与数值位之间用“.”隔开
在计算机运算时会产生正负0的现象,因此在计算机存储中不会采用反码形式。
3、补码:在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。
转换
1、正数的原码、反码、补码完全一样,数值位相同;
2、负数的反码为原码符号位1不变数值位取反;
3、负数的补码为原码除符号位不变,数值位取反加一。

13.逻辑运算符
逻辑运算符用于连接布尔型表达式,在Java中不可以写成3<x<6,应该写成x>3 & x<6 。
“&”和“&&”的区别:
单&时,左边无论真假,右边都进行运算;
双&时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。
“|”和“||”的区别同理,||表示:当左边为真,右边不参与运算。
异或( ^ )与或( | )的不同之处是:当左右都为true时,结果为false。 理解:异或,追求的是“异”!

14.位运算符

被移位的二进制最高位是0,右移后,空缺位补0; 最高位是1,空缺位补1。

被移位二进制最高位无论是0或者是1,空缺位都用0补。
& 二进制位进行&运算,只有1&1时结果是1,否则是0;
| 二进制位进行 | 运算,只有0 | 0时结果是0,否则是1;
运算符有不同的优先级,所谓优先级就是表达式运算中的运算顺序。如右表,上一行运算符总优先于下一行。
只有单目运算符、三元运算符、赋值运算符是从右向左运算的。
局部计算,局部比较,逻辑运算,最后赋值

15.数组
数组的定义
数组是相同类型数据的有序集合。
数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。
数组的元素是通过索引访问的,数组索引从0开始。
获取数组长度:arrays.length

16.数组初始化的方式(一维数组)
静态初始化
int[] a = {1,2,3};
System.out.println(a);//这里的a输出的是系统分配内存地址;
System.out.println(a[0]);//这里的a输出的是设置的下标为0的地址里面的值;
动态初始化
int[] a = new int[2];
a[0]=1;
a[1]=2;//这里是赋值,未赋值直接为0,sout输出直接为0。
System.out.println(a[0]);//这里的a输出的是设置的下标为0的地址里面的值;
数组的默认初始化
数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
(二维数组)
int a[][]=new int[2][5];//二维数组,写的是一个2行5列的二维数组,动态初始化;
int[][] b={{1,2},{3,5},{4,6},{3,9}};//静态初始化;

17.数组的四个基本特点
其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。
其元素必须是相同类型,不允许出现混合类型。
数组中的元素可以是任何数据类型,包括基本类型和引用类型。
数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。

18.数组越界异常
下标的合法区间:[0, length-1],如果越界就会报错;
例:
public static void main( String[] args) {
int[] a=new int[2];
system.out.println(a[2]);
}

19.数组的工具类java.util.Arrays
由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。
给数组赋值:通过fill方法。
对数组排序:通过sort方法,按升序。
比较数组:通过equals方法比较数组中元素值是否相等。
查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。

20.Java 虚拟机在创建一个对象时都包含以下步骤:
给对象分配内存。
将对象的实例变量自动初始化为其变量类型的默认值。
初始化对象,给实例变量赋予正确的初始值。

21.类的访问控制符
只能是空或者 public;
方法和属性的访问控制符有 4 个;
分别是 public、 private、protected 和 friendly;
其中 friendly 是一种没有定义专门的访问控制符的默认情况。

22.各种访问修饰符的可访问性
访问范围 private friendly(默认) protected public
同一个类 可访问 可访问 可访问 可访问
同一包中的其他类 不可访问 可访问 可访问 可访问
不同包中的子类 不可访问 不可访问 可访问 可访问
不同包中的非子类 不可访问 不可访问 不可访问 可访问

23.类的成员变量可以分为以下两种:
静态变量(或称为类变量),指被 static 修饰的成员变量。
实例变量,指没有被 static 修饰的成员变量。
静态变量与实例变量的区别如下:

1)静态变量
运行时,Java 虚拟机只为静态变量分配一次内存,在加载类的过程中完成静态变量的内存分配。
在类的内部,可以在任何方法内直接访问静态变量。
在其他类中,可以通过类名访问该类中的静态变量。

2)实例变量
每创建一个实例,Java 虚拟机就会为实例变量分配一次内存。
在类的内部,可以在非静态方法中直接访问实例变量。
在本类的静态方法或其他类中则需要通过类的实例对象进行访问。
静态变量在类中的作用如下:
静态变量可以被类的所有实例共享,因此静态变量可以作为实例之间的共享数据,增加实例之间的交互性。
如果类的所有实例都包含一个相同的常量属性,则可以把这个属性定义为静态常量类型,从而节省内存空间。例如,在类中定义一个静态常量 PI。

24.通用命令。
String result = Integer.toBinaryString(a);//十进制转二进制
System.out.println("二进制数为:"+result);

Arrays.toString()//打印数组
Math.random()//生成随机数
Arrays.sort()//排序,默认升序
Arrays.fill(fromindex,toindex,val)//填充数组从...到,以val填充,索引从0开始,左闭右开。
Math.sqrt()//平方和
Arrays.binarySearch()//数组搜索,返回下标值
Arrays.Stream()//转换stream流
Arrays.asList()//转换List

25.方法重载
多个方法在同一个类中
多个方法具有相同的方法名
多个方法的参数不相同,类型不同或者数量不同
特点:
重载仅对应方法的定义,与方法的调用无关,调用方式参照标准格式
重载仅针对同一个类中方法的名称与参数进行识别。
(与返回值无关,换句话说不能通过返回值来判定两个方法是否相互构成重载)

26.方法所属性
方法不能独立定义,只能定义在类里;
方法要么属于一个类,要么属于一个对象;
方法不能独立执行,必须要有调用者(对象.方法,类.方法)

27.形参长度可变的方法
如果在定义方法时,在最后一个参数的类型后增加三点...
则表明该形参接受多个相同类型的参数值
多个参数值被当成数组传入长度可变的形参只能位于最后一个参数
并一个方法里只能有一个可变长度的参数

public static void sc(int a,int...other){}
public static void sc(int a,int[]b,float c){}
这里的int...other相当于int[]b是数组的意思,也就是说里面可以调用传参不止一个数,根据方法的数据类型可以传很多数值。、

28.对象,引用和指针;
堆(Heap) ,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
栈(Stack),是指虚拟机栈。虚拟机栈用于存储局部变量等局部变量表存放卞编译期可知长度的各种基本数据类型(boolean、 byte、char 、 short 、 int 、 float 、 long、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址)。方法执行完,自动释放。
方法区(Method Area),用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

29.继承的概念:
继承是类与类的一种关系,是一种“is a”的关系。比如“狗”继承“动物”,这里动物类是狗类的父类或者基类,狗类是动物类的子类或者派生类。
注:java中的继承是单继承,即一个类只有一个父类。
继承的好处:
子类拥有父类的所有属性和方法(除了private修饰的属性不能拥有)从而实现了实现代码的复用; 
方法的重写

子类如果对继承的父类的方法不满意(不适合),可以自己编写继承的方法,这种方式就称为方法的重写。当调用方法时会优先调用子类的方法。

重写要注意:
a、返回值类型
b、方法名
c、参数类型及个数
都要与父类继承的方法相同,才叫方法的重写。

30.重载和重写的区别:

    方法重载:在同一个类中处理不同数据的多个相同方法名的多态手段。
    方法重写:相对继承而言,子类中对父类已经存在的方法进行区别化的修改。

继承的初始化顺序

1、初始化父类再初始化子类

2、先执行初始化对象中属性,再执行构造方法中的初始化。

基于上面两点,我们就知道实例化一个子类,java程序的执行顺序是:

父类对象属性初始化---->父类对象构造方法---->子类对象属性初始化--->子类对象构造方法 
  
31.final关键字
使用final关键字做标识有“最终的”含义。
1. final 修饰类,则该类不允许被继承。
2. final 修饰方法,则该方法不允许被覆盖(重写)。
3. final 修饰属性,则该类的该属性不会进行隐式的初始化,所以 该final 属性的初始化属性必须有值,或在构造方法中赋值(但只能选其一,且必须选其一,因为没有默认值!),且初始化之后就不能改了,只能赋值一次。
4. final 修饰变量,则该变量的值只能赋一次值,在声明变量的时候才能赋值,即变为常量。
32.super关键字
在对象的内部使用,可以代表父类对象。
1、访问父类的属性:super.age
2、访问父类的方法:super.eat()
super的应用:
首先我们知道子类的构造的过程当中必须调用父类的构造方法。其实这个过程已经隐式地使用了我们的super关键字。
这是因为如果子类的构造方法中没有显示调用父类的构造方法,则系统默认调用父类无参的构造方法。
那么如果自己用super关键字在子类里调用父类的构造方法,则必须在子类的构造方法中的第一行。
要注意的是:如果子类构造方法中既没有显示调用父类的构造方法,而父类没有无参的构造方法,则编译出错。
(补充说明,虽然没有显示声明父类的无参的构造方法,系统会自动默认生成一个无参构造方法,但是,如果你声明了一个有参的构造方法,而没有声明无参的构造方法,这时系统不会动默认生成一个无参构造方法,此时称为父类有没有无参的构造方法。)

32.抽象类定义:
用abstract关键字来修饰一个类,这个类叫做抽象类。
用abstract来修饰一个方法,该方法叫做抽象方法。
抽象方法:只有方法的声明,没有方法的实现。
以分号结束:比如: public abstract void talk(); I
含有抽象方法的类必须被声明为抽象类。
抽象类不能被实例化。抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,供方法体。若没有重写全部的抽象方法,子类必须也定义为抽象类。
不能用abstract修饰属性、代码块、构造器;
不能用abstract修饰私有方法、静态方法、final的方法、final的类。

抽象类前使用abstract关键字修饰,则该类为抽象类。
使用抽象类要注意以下几点:
1. 抽象类是约束子类必须有什么方法,而并不关注子类如何实现这些方法。
2. 抽象类应用场景:
a. 在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法(可实现动态多态)。
b. 从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为子类的模板,从而避免子类设计的随意性。
3. 抽象类定义抽象方法,只有声明,不需要实现。抽象方法没有方法体以分号结束,抽象方法必须用abstract关键字来修饰。
33.
static方法
静态方法可以直接通过本类名直接调用;
在静态方法中不能访问类的非静态成员变量和非静态成员方法,
因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
但是在非静态成员方法中是可以访问静态成员方法/变量的
static变量
static变量也称作静态变量
静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,
它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,
在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。
Java中的static关键字不会影响到变量或者方法的作用域。在Java中能够影响到访问权限的只有private、public、protected(包括包访问权限)这几个关键字。

34.向上转型、向下转型
引用类型转换:

  1. 向上类型转换(隐式/自动类型转换),是小类型转换到大类型。
    当父类的引用可以指向子类的对象时,就是向上类型转换。如:
    Dog dog = new Dog();
    Animal animal = dog;//自动类型提升向上类型转换
  2. 向下类型转换(强制类型转换),是大类型转换到小类型(有风险,可能出现数据溢出)
    Dog dog = new Dog();
    Dog dog=(Dog)animal ;//向下类型转换强制类型转换
    但是如果父类引用没有指向该子类的对象,则不能向下类型转换,虽然编译器不会报错,但是运行的时候程序会出错

35.instanceof运算符
instanceof是Java的一个二元操作符,和,>,<是同一类东东。
由于它是由字母组成的,所以也是Java的保留关键字。
它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。
补充说明:在比较一个对象是否和另一个对象属于同一个类实例的时候
我们通常可以采用instanceof和getClass两种方法通过两者是否相等来判断
但是两者在判断上面是有差别的。
Instanceof进行类型检查规则是:你属于该类吗?或者你属于该类的派生类吗?
而通过getClass获得类型信息采用
来进行检查是否相等的操作是严格的判断
不会存在继承方面的考虑;

36.内部类
1.成员内部类的使用方法:
  1、 Inner 类定义在 Outer 类的内部,相当于 Outer 类的一个成员变量的位置,Inner 类可以使用任意访问控制符,如 public 、 protected 、 private 等
  2、 Inner 类中定义的 test() 方法可以直接访问 Outer 类中的数据,而不受访问控制符的影响,如直接访问 Outer 类中的私有属性a
  3、 定义了成员内部类后,必须使用外部类对象来创建内部类对象,而不能直接去 new 一个内部类对象,即:内部类 对象名 = 外部类对象.new 内部类( );
外部类是不能直接使用内部类的成员和方法
外部类如何使用内部类的成员和方法呢??
答:可先创建内部类的对象,然后通过内部类的对象来访问其成员变量和方法。
Java 编译器在创建内部类对象时,隐式的把其外部类对象的引用也传了进去并一直保存着。这样就使得内部类对象始终可以访问其外部类对象,同时这也是为什么在外部类作用范围之外向要创建内部类对象必须先创建其外部类对象的原因。
如果外部类和内部类具有相同的成员变量或方法,内部类默认访问自己的成员变量或方法,如果要访问外部类的成员变量,可以使用 this 关键字。
2.静态内部类
静态内部类是 static 修饰的内部类,这种内部类的特点是:
1、 静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问。
2、 如果外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员;如果外部类的静态成员与内部类的成员名称不相同,则可通过“成员名”直接调用外部类的静态成员。
3、 创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名= new 内部类();
3.方法内部类
方法内部类就是内部类定义在外部类的方法中,方法内部类只在该方法的内部可见,即只在该方法内可以使用。
一定要注意哦:由于方法内部类不能在外部类的方法以外的地方使用,因此方法内部类不能使用访问控制符和 static 修饰符。
4.匿名内部类
匿名类是不能有名称的类,所以没办法引用他们。必须在创建时,作为new语句的一部分来声明他们。
但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口。
这就要采用另一种形式 的new语句,如下所示:
new <类或接口> <类的主体>
这种形式的new语句声明一个新的匿名类,他对一个给定的类进行扩展,或实现一个给定的接口。他还创建那个类的一个新实例,并把他作为语句的结果而返回。要扩展的类和要实现的接口是 new语句的操作数,后跟匿名类的主体
注意匿名类的声明是在编译时进行的,实例化在运行时进行。这意味着 for循环中的一个new语句会创建相同匿名类的几个实例,而不是创建几个不同匿名类的一个实例。
从技术上说,匿名类可被视为非静态的内部类,所以他们具备和方法内部声明的非静态内部类相同的权限和限制。
只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现
1、使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
2、匿名内部类中是不能定义构造函数的。
3、匿名内部类中不能存在任何的静态成员变量和静态方法。
4、匿名内部类为局部内部类(即方法内部类),所以局部内部类的所有限制同样对匿名内部类生效。
5、匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。

37.匿名内部类重点难点:

  1. 如果是在一个方法的匿名内部类,可以利用这个方法传进你想要的参数,不过记住,这些参数必须被声明为 final
    2.匿名内部类中使用初始化代码块
    我们一般都是利用构造器来完成某个实例的初始化工作的,但是匿名内部类是没有构造器的!那怎么来初始化匿名内部类呢?使用构造代码块!利用构造代码块能够达到为匿名内部类创建一个构造器的效果。

38.初始化
非静态代码块:没有static修饰的代码块
可以有输出语句。
可以对类的属性、类的声明进行初始化操作。
除了调用非静态的结构外,还可以调用静态的变量或方法。
若有多个非静态的代码块,那么按照从上到下的顺序依次执行。
每次创建对象的时候,都会执行一次。且先于构造器执行。

静态代码块:用static 修饰的代码块
可以有输出语句。
可以对类的属性、类的声明进行初始化操作。
不可以对非静态的属性初始化。即:不可以调用非静态的属性和方法。
若有多个静态的代码块,那么按照从上到下的顺序依次执行。
静态代码块的执行要先于非静态代码块。
静态代码块随着类的加载而加载,且只执行一次。

39.使用构造器执行初始化
思考:构造器是创建Java对象的途径,是不是说构造器完全负责创建Java对象呢?
实际上,当调用构造器时,系统会先为该对象分布内存空间,
并未这个对象执行默认初始化,这个对象已经产生了,
这些操作在构造器执行之前都已经完成了;只不讨这个对象还不能被外部访尚,
当构诰器执行完毕后,会把这个对象返回并赋值给一个引用类型的变量。
构造器初始化,有参代替无参,默认无参

40.this在构造器中的使用

可以在类的构造器中使用"this(形参列表)"的方式,调用本类中重载的其他的构造器
明确:构造器中不能通过"this(形参列表)"的方式调用自身构造器
如果一个类中声明了n个构造器,则最多有n-1个构造器中使用了"this(形参列表)
"this(形参列表)"必须声明在类的构造器的首行!|
在类的一个构造器中,最多只能声明一个"this(形参列表)“
this调用自己的构造器,实际上就是代码复用,我们在一个构造器里实现的逻辑
在其他的构造器里就没有必要再写一次了,直接用this调用就可以了。

41.接口的定义
●接口(interface)是抽象方法和常量值定义的集合。
●接口的特点:
➢用interface来定义。
➢接口中的所有成员变量都默认是由public static final修饰的。
➢接口中的所有抽象方法都默认是由publicabstract修饰的。
➢接口中没有构造器。
➢接口采用多继承机制。

42.接口的实现
●一个类可以实现多个接口,接口也可以继承其它接口。
●实现接口的类中必须提供接口中所有方法的具体实现内容,方可实例化。否则,仍为抽象类
●接口的主要用途就是被实现类实现。( 面向接口编程)
●与继承关系类似,接口与实现类之间存在多态性
●接口和类是并列关系,或者可以理解为一种特殊的类。从本质上讲,接口是一种特殊的抽象类,
这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。

43.和equals方法
基本类型比较值:只要两个变量的值相等,即为true。
引用类型比较引用(是否指向同-一个对象):只有指向同一个对象时,
才返回true。
用“==”进行比较时,符号两边的数据类型必须具有继承关系(可自动转换的基本数据类型除外,否则编译出错

●equals() :所有类都继承了Object●也就获得了equals()方法。还可以重写。
➢只能比较引用类型,其作用与“=="相同 ,比较是否指向同一个对象。
➢格式:obj1 equals(obj2)
●特例:当用equals()方法进行比较时,对类File 、String 、Date及包装类( Wrapper Class)来说,是
比较类型及内容而不考虑引用的是否是同一个对象;
➢原因:在这些类中重写了Object类的equals()方法●
●当自定义使用equals()时.可以重写。用于比较两个对象的“内容”是否都相等
●equals从写规则
➢两个对象的她址值相同.返回true
➢参数为null,两个对象不属于同一个类,返回false
➢比较属性值,如果属性相同,返回true ;不相同返回false

44.String、StringBuffer、StringBuilder
●StringBuilder和StringBuffer非常类似.均代表可变的字符序列,而且提供相关功能的方法也一样
●面试题:对比String、StringBuffer、StringBuilder
➢String(JDK1.0):不可变字符序列.
➢StringBuffer(JDK1.0);可变字符序列、效率低、线程安全
➢StringBuilder(JDK5.0):可变字符序列、效率高、线程不安全
●注意:作为参数传递的话,方法内部String不会改变其值,StringBuffer和StringBuilder会改变其值。
●结论:如果我们的代码有线程安全问题,使用StringBuffer: 没有线程安全问题,使用StringBuilder,我们在开发
中,线程安全问题出现的概率是要小于非安全的,在大多数场景下使用的是StringBuilder

45.捕获和不捕获异常,程序的运行有什么不同。
➢捕获的话就是按照我们自己的需求来处理异常;不捕获的话的直接把异常抛给JVM,JVM会终止程序,并在控制台打
印异常信息
●体会try语句块中可能发生多个不同异常时的处理。
➢多个异常有没有继承关系,如果有的话,父类的异常一定要放下面;如果没有继承关系的话,顺序没有要求
●体会finally语句块的使用。
●只要是JVM不退出, finally是- 定会执行的,释放资源一 般都会选择方法finally代码块里面

46.正则表达式中的特殊字符

  • 指定前面子表达式可以出现零次或多次。要匹配 * 字符,请使用 *
  • 指定前面子表达式可以出现一次或多次。要匹配 + 字符,请使用 +
    ? 指定前面子表达式可以出现零次或一次。要匹配 ? 字符,请使用 ?
    . 匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 .
    . 可以匹配任何字符
    \d 匹配0~9的所有数字
    \D 匹配非数字
    \s 匹配所有空白字符,包括空格、制表符、回车符、换页符、换行符等
    \S 匹配所有非空白字符
    \w 匹配所有单词字符,包括0~9所有数字,26个英文字母和下划线(_)
    \W 匹配所有非单词字符
    ^ 行的开头
    $ 行的结尾
    \b 单词的边界
    \B 非单词的边界
    上面的7个预定义字符其实很容易记忆:
    d是 digit的意思,代表数字
    s是space的意思,代表空白
    w是 word 的意思,代表单词
    d、s、w的大写形式恰好匹配与之相反的字符

表示枚举 例如[abc],表示a、b、c其中任意一个字符;[gz]表示g、z其中的任意一个字符
表示范围:- 例如[a-f],表示af范围内的任意字符;[\u0041-\u0056]表示十六进制字符\u0041到\u0056范围的字符。范围可以和枚举结合使用,如[a-cx-z],表示ac、x~z范围内的任意字符
表示求否:^ 例如:[abc],表示非a、b、c的任意字符;[a-f]表示不是a~f范围内的任意字符
表示“与”运算:&& 例如[a-z&&[def]],求a-z和[def]的交集,表示d、e或f;
[a-z&&[^bc]],a-z范围内的所有字符,除了b和c之外,即[ad-z];
[a-z&&[^m-p]],a-z范围内的所有字符,除了m~p范围之外,即[a-lq-z]
表示“并”运算 并运算与前面的枚举类似。
如[a-d[m-p]],表示[a-dm-p]

47.使用正则表达式
// 将一个表达式编译成Pattern对象
Pattern p = Pattern.compile("ab");
// 调用Pattern对象matcher方法匹配字符串, 返回Matcher对象
Matcher m = p.matcher("aaaaab");
// 根据需求调用Matcher方法
boolean b = m.matches();
System.out.println(b);
// 如果某个正则表达式仅需使用一次,可以直接使用Pattern类的静态matches方法
// 每次使用都需要重新编译得到Pattern对象,效率不高
boolean b1 = Pattern.matches("a
b", "aaaaab");

48.Matcher的API
find():返回目标字符串中是否包含与 Pattern 匹配的子串
group():返回上一次与Pattern匹配的子串, 一定要先调用find()才能调用group()
start():返回上一次与Pattern 匹配的子串在目标字符串中的开始位置
end():返回上一次与Pattern 匹配的子串在目标字符串中的结束位置加1
lookingAt():返回目标字符串前面部分与Pattern是否匹配
matches():返回整个目标字符串与 Pattern是否匹配
reset():将现有的 Matcher对象应用于一个新的字符序列
replaceAll():将匹配的所有子串替换为目标字符串, 和字符串replaceAll()功能是一样
replaceFirst():将匹配的第一个子串替换为目标字符串, 和字符串replaceFirst()功能是一样
matches()和 lookingAt()方法有点相似,只是matches()方法要求整个字符串和Pattern 完全匹配时返回true,而 lookingAt()只要字符串以Pattern开头就会返回true。
reset()方法可将现有的Matcher对象应用于新的字符串。

49.Set和List的区别

  1. Set 接口实例存储的是无序的,不重复的数据。List 接口实例存储的是有序的,可以重复的元素。
  2. Set 检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet>。
  3. List 和数组类似,可以动态增长,根据实际存储的数据的长度自动增长 List 的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector> 。

50.ArrayLIst
Java ArrayList 常用方法列表如下:
方法 描述
add() 将元素插入到指定位置的 arraylist 中
addAll() 添加集合中的所有元素到 arraylist 中
clear() 删除 arraylist 中的所有元素
clone() 复制一份 arraylist
contains() 判断元素是否在 arraylist
get() 通过索引值获取 arraylist 中的元素
indexOf() 返回 arraylist 中元素的索引值
removeAll() 删除存在于指定集合中的 arraylist 里的所有元素
remove() 删除 arraylist 里的单个元素
size() 返回 arraylist 里元素数量
isEmpty() 判断 arraylist 是否为空
subList() 截取部分 arraylist 的元素
set() 替换 arraylist 中指定索引的元素
sort() 对 arraylist 元素进行排序
toArray() 将 arraylist 转换为数组
toString() 将 arraylist 转换为字符串
ensureCapacity() 设置指定容量大小的 arraylist
lastIndexOf() 返回指定元素在 arraylist 中最后一次出现的位置
retainAll() 保留 arraylist 中在指定集合中也存在的那些元素
containsAll() 查看 arraylist 是否包含指定集合中的所有元素
trimToSize() 将 arraylist 中的容量调整为数组中的元素个数
removeRange() 删除 arraylist 中指定索引之间存在的元素
replaceAll() 将给定的操作内容替换掉数组中每一个元素
removeIf() 删除所有满足特定条件的 arraylist 元素
forEach() 遍历 arraylist 中每一个元素并执行特定操作

for(int i : myNumbers)
等价于:

for(int i = 0; i < myNumbers.size(); i++){
int j = myNumbers.get(i);
}

51.Iterator迭代器接口
Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。
Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力。如果需要创Iterator 对象,则必须有一个被迭代的集合。
集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
在迭代的过程中如果对集合进行add、remove操作都会抛出 ConcurrentModificationException 快速失败异常。
Iterator it = sites.iterator();

51.Java集合类可以用于存储数量不等的多个对象,还有用于保存具有映射关系的关联数组。
集合的长度是可变的
集合里面只能存放引用数据类型
提供了很多操作元素的方法
Collection集合
collection包括List和Set.
list有ArrayList和linkedlist和vector三种
set有Hashset,sortedset,linkedhashset以及Treeset
iterator是一个迭代器,用于获取List集合
JDK提供的集合API位于java.util包下
Map集合
Map有Hashtable,HashMap,sortedmap,properites,ListHashMap以及TreeMap

Iterator可以删除集合的元素,但是是遍历过程中通过迭代器对象的remove方法,不是集合对象的remove方法。
remove方法的调用应该方法next后面, 否则会报IllegalStateException异常
remove方法不能重复调用, 否则会报IllegalStateException异常
Iterator迭代器基于面向接口编程思想, 集合获取的迭代器是每个集合类的内部类

53.List接口概述
鉴于Java中数组用来存储数据的局限性,我们通常使用List替代数组
List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector。

54.Arrays工具类里提供了asList(Object...a)方法,该方法可以把一个数组、或指定个数的对象转换成一个List集合,这个List集合既不是ArrayList实现类的实例,也不是Vector实现类的实例,而是Arrays的内部类ArrayList的实例。
Arrays.ArrayList是一个固定长度的List集合,程序只能遍历访问该集合里的元素,不可增加、删除该集合里的元素

55.ArrayList和LinkedList的对比
ArrayList基于数组实现:
查询、添加快(末尾添加数据)
插入数据慢
LinkedList双向链表实现:
查询慢,要根据头结点或者是尾节点遍历查询
插入数据效率比较高
时间复杂度的判断,就是看代码是否有循环,有循环(效率低),没有的话(效率高)

56.Set接口是Collection的子接口,set接口没有提供额外的方法
Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个Set 集合中,则添加操作失败。
Set 判断两个对象是否相同不是使用 ==运算符,而是根据 equals() 方法

57.HashSet
HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。
HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取、查找、删除性能。
HashSet 具有以下特点:
不能保证元素的排列添加顺序
HashSet 不是线程安全的
集合元素可以是 null
HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。
对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Object obj)方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”。

58.为什么要按照规则同时重写hashCode和equals方法?
如果equals方法都返回了true,就代表了这两个对象相等;hashCode返回了false,那么这两个对象是可以重复保存到Set里面的,那不就和Set里面不能保存重复元素这个定义矛盾了吗?所以重写equals方法是不够的,必须还要重写hashCode方法。
结论:重写equals方法的时候一般都需要同时复写hashCode方法。通常参与计算hashCode的对象的属性也应该参与到equals()中进行计算

TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。
TreeSet底层使用红黑树结构存储数据
TreeSet 两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。
TreeSet和后面要讲的TreeMap采用红黑树的存储结构

特点:有序,查询速度比链表快
红黑树O(logn), 链表0(1)
TreeSet的自然排序要求元素所属的类实现Comparable接口;我们想要往TreeSet里添加一些自定义的类,compareTo方法的逻辑就必须要我们自己编写,就是定制排序。
要实现定制排序,需要将实现Comparable接口,重写compareTo方法。
此时,仍然只能向TreeSet中添加类型相同的对象。否则发生ClassCastException异常。
向 TreeSet 中添加元素时,只有第一个元素无须比较compareTo()方法,后面添加的所有元素都会调用compareTo()方法进行比较。
使用定制排序判断两个元素相等的标准是:通过compareTo方法是否返回0。
当需要把一个对象放入 TreeSet 中,重写该对象对应的 equals() 方法时,应保证该方法与 compareTo(Object obj) 方法有一致的结果;如果两个对象通过 equals() 方法比较返回 true,则通过 compareTo(Object obj) 方法比较应返回 0。 否则,就违背了Set的定义。
定制排序也可以使用构造方法设置排序规则,设置好规则后,add的元素无需实现Comparable接口
public TreeMap(Comparator<? super K> comparator)
利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。

60.HashMap是 Map 接口使用频率最高的实现类。
允许使用null键和null值,与HashSet一样,不保证映射的顺序。
所有的key构成的集合是Set:无序的、不可重复的。所以,key所在的类要重写:equals()和hashCode()
一个key-value构成一个entry
所有的entry构成的集合是Set:无序的、不可重复的
HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。

61.HashMap核心变量
DEFAULT_INITIAL_CAPACITY : HashMap 的 默 认 容 量 ,16
MAXIMUM_CAPACITY : HashMap 的 最 大 支 持 容 量 ,2^30
DEFAULT_LOAD_FACTOR:HashMap的默认加载因子,0.75
TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树 8
UNTREEIFY_THRESHOLD:Bucket中红黑树存储的Node小于该默认值,转化为链表 6
table:存储元素的数组,总是2的n次幂
size:HashMap中存储的键值对的数量
threshold:扩容的临界值,= 容量 * 负载因子
entrySet:存储具体元素的集
modCount:HashMap扩容和结构改变的次数

62.面试题:负载因子值的大小,对HashMap有什么影响
负载因子的大小决定了HashMap的数据密度。
负载因子越大密度越大,发生hash冲突几率越高,数组中的链表越容易长, 造成查询或插入时的比较次数增多,性能会下降。
负载因子越小,就越容易触发扩容,数据密度也越小,意味着发生碰撞的 几率越小,数组中的链表也就越短,查询和插入时比较的次数也越小,性 能会更高。但是会浪费一定的内容空间。而且经常扩容也会影响性能,建 议初始化预设大一点的空间。
按照其他语言的参考及研究经验,不要修改,就用默认的0.75,此时平均检索长度接近于常数。

63.LinkedhashMap
LinkedHashMap 是 HashMap 的子类
在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序
与LinkedHashSet类似,LinkedHashMap 可以维护 Map 的迭代顺序:迭代顺序与 Key-Value 对的插入顺序一致

64.TreeMap
TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序。TreeMap 可以保证所有的 Key-Value 对处于有序状态。
TreeSet底层使用红黑树结构存储数据
TreeMap 的 Key 的排序:
自然排序:TreeMap 的所有的 Key 必须实现 Comparable 接口,而且所有 的 Key 应该是同一个类的对象,否则将会抛出 ClasssCastException
定制排序:
1,TreeMap的key对象实现Comparable接口,实现compareTo方法,实现比较逻辑
2,创建 TreeMap 时,传入一个 Comparator 对象,该对象负责对 TreeMap 中的所有 key 进行排序。此时不需要 Map 的 Key 实现 Comparable 接口
TreeMap判断两个key相等的标准:两个key通过compareTo()方法或者compare()方法返回0。

65.Hashtable
Hashtable是个古老的 Map 实现类,JDK1.0就提供了。不同于HashMap,Hashtable是线程安全的。
Hashtable实现原理和HashMap相同,功能相同。底层都使用哈希表结构,查询速度快,很多情况下可以互用。
与HashMap不同,Hashtable 不允许使用 null 作为 key 和 value
与HashMap一样,Hashtable 也不能保证其中 Key-Value 对的顺序
Hashtable判断两个key相等、与HashMap一致(hashCode, equals)。

66.Properties
Properties 类是 Hashtable 的子类,该对象用于处理属性文件
由于属性文件里的 key、value 都是字符串类型,所以 Properties 里的 key和 value 都是字符串类型
存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法

67.Collections工具类
Collections 是一个操作 Set、List 等集合的工具类
Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法
排序操作:(均为static方法)
reverse(List):反转 List 中元素的顺序
shuffle(List):对 List 集合元素进行随机排序
sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
查找、替换
Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
Object min(Collection)
Object min(Collection,Comparator)
int frequency(Collection,Object):返回指定集合中指定元素的出现次数
void copy(List dest,List src):将src中的内容复制到dest中,如果dest的容量不够会报错
boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值

68.文件流

File file=new File("E:\日常文件\兰智数加\Java 兰智20220627");

69.节点输入流、输出流
(1)字节输入流.输出流

InputStream is = new FileInputStream("C:\eclipse-workspace"))
OutputStream is = new FileOutputStream("C:\eclipse-workspace"))

(2)字符输入流,输出流
Writer isr = new FileWriter("C:\eclipse-workspace"))
Reader isr = new FileReader("C:\eclipse-workspace"))

70.转换流
字节输出流转字符输出流
OutputStreamWriter oSt = new OutputStreamWriter(new FileOutputStream("C:\eclipse-workspace")
字节输入流转字符输入流
InputStreamReader isr = new InputStreamReader( new FileInputStream("C:\eclipse-workspace"))

71.缓冲流
BufferedWriter
void newLine() 换行
BufferedReader
String readLine() 读取一行
输入字符流嵌套于缓冲字符输入流
BufferedReader bis=new BufferedReader(new FileReader("C:\eclipse-workspace"));
输出字符流嵌套于缓冲字符输出流
BufferedWriter bos=new BufferedWriter( new FileWriter("C:\eclipse-workspace"))

72.数据流
字节输入流嵌套于数据字节输入流
DataInputStream dis= new DataInputStream(new FileInputStream("destData.dat"))
字节输出流嵌套于数据字节输出流
DataOutputStream dos= new DataOutputStream(new FileOutputStream("destData.dat"))

73.对象流
字节输入流嵌套于对象字节输入流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("file/obj"))
字节输出流嵌套于对象字节输出流
ObjectOutputStream ops = new ObjectOutputStream(new FileOutputStream("file/obj"))

74.随机存取文件流
读取文件内容
RandomAccessFile raf = new RandomAccessFile(“test.txt”, “rw”); raf.seek(5);

posted @ 2022-08-31 21:30  996开发  阅读(73)  评论(0)    收藏  举报