JDK基础
JDK,JRE,JVM的作用及关系(掌握)
- 作用
- JVM:保证Java语言跨平台
- JRE:Java程序的运行环境
- JDK:Java程序的开发环境
- 关系
- JDK:JRE+工具
- JRE:JVM+类库
java常识
关键字
- 被Java语言赋予特定含义的单词
- 特点:
全部小写。 - 注意事项:goto和const作为保留字存在。
标识符
-
就是给类,接口,方法,变量等起名字的字符序列
- 组成规则:
A:英文大小写字母
B:数字
C:$和_ - 注意事项:
A:不能以数字开头
B:不能是java中的关键字
C:区分大小写
- 组成规则:
数据类型
基本数据类型
A:整数 占用字节数
byte 1
short 2
int 4
long 8
B:浮点数
float 4
double 8
C:字符
char 2
D:布尔
boolean 1
注意:
整数默认是int类型,浮点数默认是double。
长整数要加L或者l。
单精度的浮点数要加F或者f。
数据转换
默认转换
A:从小到大
B:byte,short,char -- int -- long -- float -- double
C:byte,short,char之间不相互转换,直接转成int类型参与运算。、
请自己实现两个整数变量的交换,不用第三个变量
用位异或实现
因为:aba=b.一个数异或两次等于同一个数
int a=10,int b=10;
a=a^b;
b=a^b;
a=a^b;
用变量相加的做法
a=a+b;
b=a-b;
a=a-b;
一句话搞定
b=(a+b)-(a=b)
请用最有效率的方式计算出2乘以8的结果
2<<3
代码块
- 用{}括起来的代码。
- 分类:
- 局部代码块
用于限定变量的生命周期,及早释放,提高内存利用率。 - 构造代码块
把多个构造方法中相同的代码可以放到这里,每个构造方法执行前,首先执行构造代码块。 - 静态代码块
对类的数据进行初始化,仅仅只执行一次。
- 局部代码块
- 静态代码块,构造代码块,构造方法的顺序问题?
静态代码块 > 构造代码块 > 构造方法
面向对象
- 成员变量和局部变量的区别
- 位置不同
- 内存中位置不同
- 生命周期不同
- 初始化值不同
继承
高内聚低耦合,类里面单独实现方法,类与类之间减少关联就是低耦合
虽然子类中构造方法默认有一个super()
初始化的时候,不是按照那个顺序进行的。
而是按照分层初始化进行的。
它仅仅表示要先初始化父类数据,再初始化子类数据。
多态
多态中的成员访问特点
- 成员变量
编译看左边,运行看左边 - 构造方法
子类的构造都会默认访问父类构造 - 成员方法
编译看左边,运行看右边 - 静态方法
编译看左边,运行看左边
为什么?
因为成员方法有重写。
接口
接口的成员特点:
- 成员变量
只能是常量
默认修饰符:public static final - 构造方法
没有构造方法 - 成员方法
只能是抽象的
默认修饰符:public abstract
内部类
成员内部类常见修饰符号
- private 为了数据的安全性
- static 为了访问的方便性
成员内部类不是静态的:
外部类名.内部类名 对象名 = new 外部类名.new 内部类名();
成员内部类是静态的:
外部类名.内部类名 对象名 = new 外部类名.内部类名();
局部内部类
- 可以直接访问外部类成员
- 在局部位置,可以创建内部类对象,通过对象调用内部类方法
面试题:
局部内部类访问局部变量必须使用final修饰为什么呢?
局部变量是随着方法的调用而调用,随着调用完毕而消失。而堆内存的内容并不会立即消失,所以我们加final修饰,加入final修饰后,变量就变成了常量,既然是常量,你消失了,我在内存中存储的是数据数值,还是有数据可以使用。
匿名内部类
本质:是一个继承了该类或者实现了该接口的子类匿名对象。
在Android开发中用的多,因为匿名内部类用完就是垃圾等待回收。不过它只能用一次。
API
Object
- toString()
返回对象的字符串表示,默认是由类的全路径+'@'+哈希值的十六进制表示。
这个表示其实是没有意义的,一般子类都会重写该方法。
如何重写呢?过程我也讲解过了,基本上就是要求信息简单明了。
但是最终还是自动生成。 - equals()
比较两个对象是否相同。默认情况下,比较的是地址值是否相同。
而比较地址值是没有意义的,所以,一般子类也会重写该方法。
重写过程,我也详细的讲解和分析了。
但是最终还是自动生成。 - hashCode() 返回对象的哈希值。不是实际地址值,可以理解为地址值。
- getClass() 返回对象的字节码文件对象,反射中我们会详细讲解
- finalize() 用于垃圾回收,在不确定的时间
- clone() 可以实现对象的克隆,包括成员变量的数据复制,但是它和两个引用指向同一个对象是有区别的。
- 直接输出一个对象名称,其实默认调用了该对象的toString()方法。
面试题
==和equals()的区别?
- ==
基本类型:比较的是值是否相同
引用类型:比较的是地址值是否相同 - equals()
只能比较引用类型。默认情况下,比较的是地址值是否相同。
但是,我们可以根据自己的需要重写该方法。
Scanner
Scanner scan=new Scanner(System.in);
通过这个对象先获取一个数值,在获取一个字符串,会出现问题。
如下:
int i=scan.nextInt();
String s=scan.nextLine();
主要原因是:是换行符的问题。/r/n
如何解决
- 重新获取一个键盘录入对象
- 把所有类型转换成字符串类型,在转换回来。
String类(最常见的没有之一)
字符串的特点
- 一旦被赋值就不能被改变这里的值指的是数值而不是引用。
- 字符串直接赋值的方式是先到字符串常量池里面去找,如果有直接返回,没有就创建并返回
- 字符串拼接,如果是常量相加先拼接然后再常量池中找,如果有直接返回否则创建。如果有变量拼接就是先开空间在拼接。
compareTo()字符串比较
public int compareTo(String anotherString)。按字典顺序比较,可以看源码看返回结果是什么。
String s=new String("Hello")和String s="Hello";的区别
- 前者创建两个或一个对象。
- 后者创建一个或零个对象
StringBuffer
线程安全---同步(有人操作时其他不能操作)--数据安全
StringBuffer和String的区别
前者长度可变,后者不可变
如果前者用字符串拼接,不会浪费太多的空间
他们都可以通过互相的构造方法转换成相互的对象,
StringBuffer.toString()也可转换成字符串.任何一个引用类型都可以通过toString转成String对象。
StringBuffer和StringBuilder
StringBuilder是线程不安全,效率高
StringBuffer和数组的区别
二者都可以看成一个容器,装其他数据。但是stringBufer的数据最终是一个字符串数据。而数组可以放置多种数据,但必须同一种数据类型。
Arrays
针对数组进行操作的工具类。里面有一系列方法对数组进行操作。
包装类
Integer类:下面两句代码做了哪些事情?
Integer i=1;//自动装箱,相当于Integer.valueOf(1)
i+=1;//自动拆箱在自动装箱
面试题
Integer i1=127;
Integer i2=127;
System.out.println(i1==i2);
Integer i3=128;
Integer i4=128;
System.out.println(i3==i4);
第一个输出语句为true.第二个为false
通过查看valuof这个源码,我们就知道了,针对-128到127之间的数据,做了一个数据缓存池,如果数据是该范围的,每次并不创建新的空间。
注意:Integer的数据直接赋值,如果在-128到127直接按,会直接冲缓冲池里获取数据
Random:产生随机数
public Random();没有给种子,用的是默认种子,是当前时间的毫秒值
public Random(long seed);给出指定种子(给定了种子之后,每次产生的随机数相同)
System
System 类包含一些有用的类字段和方法。它不能被实例化
System.gc()垃圾回收机制
System.gc()可用于垃圾回收。当使用System.gc()回收某个对象所占用的内存之前,通过要求程序调用适当的方法来清理资源。在没有明确指定资源清理的情况下,Java提高了默认机制来清理该对象的资源,就是调用Object类的finalize()方法。finalize()方法的作用是释放一个对象占用的内存空间时,会被JVM调用。而子类重写该方法,就可以清理对象占用的资源,该方法有没有链式调用,所以必须手动实现。
从程序的运行结果可以发现,执行System.gc()前,系统会自动调用finalize()方法清除对象占有的资源,通过super.finalize()方式可以实现从下到上的finalize()方法的调用,即先释放自己的资源,再去释放父类的资源。
但是,不要在程序中频繁的调用垃圾回收,因为每一次执行垃圾回收,jvm都会强制启动垃圾回收器运行,这会耗费更多的系统资源,会与正常的Java程序运行争抢资源,只有在执行大量的对象的释放,才调用垃圾回收最好
arraycopy(命名不规范的一个方法)
从指定数组中复制一个数组,复制从指定的位置开始,到目标位置结束。
正则表达式
符合一定规则的字符串。相关的类Pattern(在API中我们可以查看)
-
字符
- x 字符 x。举例:'a'表示字符a
- \ 反斜线字符。两个\才能代表一个因为\具有转义功能
- \n 新行(换行)符 ('\u000A')
- \r 回车符 ('\u000D')
-
字符类
- [abc] a、b 或 c(简单类)
- [^abc] 任何字符,除了 a、b 或 c(否定)
- [a-zA-Z] a到 z 或 A到 Z,两头的字母包括在内(范围)
- [0-9] 0到9的字符都包括
-
预定义字符类
- . 任何字符。我的就是.字符本身,怎么表示呢? .使用的时候是\.
- \d 数字:[0-9]。但是我们使用的时候必须\d
- \w 单词字符:[a-zA-Z_0-9]
在正则表达式里面组成单词的东西必须有这些东西组成
-
边界匹配器
- ^ 行的开头
- $ 行的结尾
- \b 单词边界
就是不是单词字符的地方。
举例:hello world?haha;xixi
-
Greedy 数量词
- X? X,一次或一次也没有
- X* X,零次或多次
- X+ X,一次或多次
- X{n} X,恰好 n 次
- X{n,} X,至少 n 次
- X{n,m} X,至少 n 次,但是不超过 m 次