1. java跨平台原理
扩展名.java --> 扩展名.class --jvm虚拟机–> 适合系统的字节编码 --> 编译执行
2. jvm jdk jre
jvm:虚拟机,实现java跨平台以及编译运行的核心
jdk: java开发工具包
jre: java运行环境
三者关系:jdk开发工具包中包括jre运行环境,如果只是运行java代码的话,只需要jre运行环境即可。jre和jdk中都包含jvm的一些部分,而jvm虚拟机中包含许多类解析器和加载器
3. 基本类型
基本类型(字节数)
byte (1)
short(2)
int(4)
long(8)
float(4)
double(8)
boolean(1)
char(2)
4. 基本数据类型转变
自动转变规则:由数据范围小的向数据范围大的转变
强制转换规则:超出基本数据类型的数据范围时间,使用强制类型转换
5.break和continue
两者都是跳出循环,只是跳出层次不同
注意:在多层循环中,最外层出现标注时间,使用beak "标注”,程序会跳出多重循环
代码如下:
int i,j;
A:for(i=0;i<3;i++) {
System.out.println("i="+i);
for(j=0;j<5;j++){
System.out.println("j="+j);
if(j==2)
break;
}
}
结果如下:
6. 类和对象的区别
类是对象的抽象,对象是类的具体实现
例子:”人类“是一个概括类,而”小王“是该类的具体实现
7. 面向对象和面向过程
两者都是编程的一种思维,现有面向过程,才有面向对象
面向对象的出现是为了补充面向过程的不足
类比:
现在有"蛋炒饭”和"盖浇饭“两种,前者是面向过程,后者是面向对象,对于”盖浇饭“而言,菜和饭都是两个具体的对象,菜不满意,可以换,饭不满意也可以换,处理就可变的很灵活,也就是程序上的可维护性良好
区别:
面向过程是函数式编程为主,面向对象是以对象为主
面向过程有类的继承和多态性,而面向过程没有
相辅相成:
面向过程将复杂的问题抽象化,简化成具体的微小问题,然后使用面向过程思维来解决
8.关键字
1)this和super
this是自身的引用,一般用于区别成员变量和局部变量
super对直接父类的引用,可以调用父类的成员变量和成员方法(private修饰不能调用)
也可调动父类的构造方法,但是只能在子类的构造方法中使用
2)static
可以修饰方法、变量、代码块、内部类
static属性属于类所有,所有实现类共享一个static属性
注意:
- static修饰的属性属于类本身,所有的实现类公用一个,在内存中只有一个
- static修饰的静态变量在方法区中,而实例变量在堆内存中
- 静态变量调用方式 类名.变量名; 类似的方式来调用
- 静态变量在类第一次使用时间就被创建了内存,静态代码块在类第一次使用时被执行,只被执行一次
- 静态方法只能访问类中的静态变量(原因:静态方法和静态方法是类特有,在类被第一次使用时间就被创建,而成员变量是在new对象之后创建内存,使用静态方法访问成员变量,可能成员变量还没有在内存中创建)
public class StaticClass {
static String name="123456";
int age;
String sex;
public StaticClass(String sex,int age) {
this.sex=sex;
this.age=age;
}
static {
System.out.println("Name:"+name);
}
public static void SS() {
System.out.println("name1111:"+name);
}
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("StaticClass:"+StaticClass.name);
StaticClass st1;
StaticClass.SS();
st1 = new StaticClass("123",10);
System.out.println("st1.name:"+st1.name);
}
}
运行结果:
结论:可以看到,静态方法在该类第一次调用时就开始运行,并且只运行一次
3) final abstract
final: final可修饰属性 类 方法。
被修饰的变量不可更改
被修饰的类不可被继承
被修饰的方法不可被重写
abstract:acstract可以修饰类和方法
被修饰的类必须被继承
被修饰的方法必须被重写
注意:final修饰的变量不可被更改,也就变成了常量。而修饰的引用类型,其引用不可被更改,但是类型的属性可被更改
4) finally finalize
finally:使用 try 和 catch 抛出异常时间使用finally.
当用异常事件
finalize: 在object对象中被定义,用于垃圾回收器删除对象之前调用,做必要清理工作
注意:
A:
public static void main(String[] args) {
try{
System.out.println("error before");
int i;
i = 10/1;
return ;
//System.out.println("error after");
}catch(Exception e){
System.out.println("error");
}finally{
System.out.println("finally");
}
}
B:
public static void main(String[] args) {
try{
System.out.println("error before");
int i;
i = 10/0;
return ;
//System.out.println("error after");
}catch(Exception e){
System.out.println("error");
}finally{
System.out.println("finally");
}
}
运行结果:
结论:可看到无论代码是否抛出异常或者使用return,finally中的代码总会被执行
5) private default public protected
访问级别如下
6) synchronized
用于给代码加锁,被修饰的代码,每次只能一个线程进入进行处理,其他线程等待
被修饰的方法被称为同步方法,被修饰的代码块被称为同步代码块
两者区别在于:
同步方法的范围较大,同步代码块可以在方法内部,相对来说范围较小
一般来说,范围越大,性能越低
9. 继承类下构造函数的加载
构造函数:
- 如果子类没有使用super或者this来调用相应构造方法,那么它自身会调动父类的无参构造方法
- 如果子类使用super来调用父类的有参构造方法,那么调动相应的有参构造方法,而不是无参构造方法
- 如果子类使用this调动自身其他构造方法,那么调用规则使用以上两个规则
- 如果是多级继承,构造参数规则会根据以上规则以此向上一级父类来调用
A:
public class Base {
String name;
public Base() {
name = "123456";
System.out.println("fu");
}
}
public class BNext extends Base{
public BNext() {
System.out.println("zi");
}
public BNext(String name) {
super.name = name;
System.out.println("name zi");
}
}
public static void main(String[] args) {
BNext base = new BNext();
}
B:
public class Base {
String name;
public Base() {
name = "123456";
System.out.println("fu");
}
public Base(String name) {
this.name = name;
System.out.println("name fu");
}
}
public class BNext extends Base{
public BNext() {
System.out.println("zi");
}
public BNext(String name) {
super(name);
System.out.println("name zi");
}
}
public static void main(String[] args) {
BNext base = new BNext("12345");
}
运行结果:
结果可看到正如上面规则所示
10. 继承下静态代码块和静态方法加载
- 静态代码块的继承,是先执行父类静态代码,之后执行子类的静态代码,并且执行在构造方法之前,也就是第一次调用时间。
- 静态方法是直接执行调用的方法,不论是重写或者重载,只有调用才有作用
public class Base {
String name;
public Base() {
name = "123456";
System.out.println("fu");
}
static {
System.out.println("static base");
}
public static void sysoName() {
System.out.println("static name");
}
public Base(String name) {
this.name = name;
System.out.println("name fu");
}
}
public class BNext extends Base{
public BNext() {
System.out.println("zi");
}
public BNext(String name) {
super(name);
System.out.println("name zi");
}
static {
System.out.println("static BNext");
}
public static void sysoName() {
System.out.println("static BNext name");
}
}
public static void main(String[] args) {
BNext base = new BNext();
BNext.sysoName();
}
执行结果:
11. == 和equals的区别
== 作用
- 基本数据类型,比较的是数值
- 对象比较的是地址
- 不能比较没有父子关系的两种类型
equals 作用
- 系统中的类一般都会重写equals方法,比较的是内容
- 类本身没用重写该方法,会调动父类的该方法
- 自定义类小覆盖父类的equals方法
注意:object的equals方法比较的地址,此时和==作用相同
12. 基本数据类型和包装类
基本数据类型都对应了java中的包装类,由于java中是面向对象,而基本数据类型不是一个具体对象,实际使用时有不便之处
- java中提供了自动拆装箱来完成基本数据类型和包装类之间的转换
- int和Integer的区别
int是基本数据类型,Integer是int的包装类
具体比较如下:
- 当new两个新的Integer时间,两者永远是不对等的(new的时间是创建了两个对象,两者的地址不等)
Integer a = new Integer(3);
Integer b = new Integer(3);
a==b --> false - new的新对象和Integer包装类的对象不对等( 包装类包装的对象是在常量池中,而new的对象实在堆中)
Integer a = new Integer(3);
Integer b = 3;
a==b --> false - new的对象和int基本类型比较时间,只要数值相等,两者就是对等的(此时比较时间,java会自动将Integer拆装成int,之后再进行比较)
Integer a = new Integer(3);
int b = 3;
a==b --> true; - 两个非new生成的对象,对于-128~127之间的数字,两者比较相等,对与该范围之外的数值,两者比较不等。
Integer a = 100;
Integer b = 100;
a==b; --> true;
Integer a = 128;
Integer b = 128;
a == b; --> false
原因如下:
public static Integer valueOf(int i){
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high){
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}
对于-128~127之间的数值,直接进行缓存,下次使用直接拿出,而范围之外的数字,则是创建了新的对象。
13. 抽象类和接口
- 抽象类中可以有构造方法。接口中不能有
- 类可以实现多个接口(has-a),但是只能继承一个抽象类(is-a)
- 接口和抽象类都不可被实例化
- 接口可继承接口,抽象类可实现接口,抽象类可继承实体类
14. java序列化
序列化:在java中将一个实体类的状态信息写入字节流,使其可以通过socket传输,或者是写入数据库、文件系统中持久化,当使用时间,将字节流拿出,重写还原创建该实体对象
15. 创建类的几种方法
- new创建对象,最常用的创建对象方法
- 通过java.lang.class或者java.lang.reflect.Constructor类的newInstance()实例方法
- 通过clon()来克隆对象
- 通过反序列话来创建对象
注意:第一种和第二种都需要通过构造方法来创建对象,第三种是直接对已有对象进行克隆,第四种是从文件中还原对象
1:
Integer a = new Integer(3);
2:
public static void main(String args[]){
try {
Class class1 = Class.forName("java.lang.Integer");
Integer a = (Integer) class1.newInstance();
}catch (Exception e){
System.out.println(e);
}
}
3:
public static void main(String args[]){
try {
Class class1 = Class.forName("java.lang.Integer");
Constructor con = class1.getConstructor();
Integer a = (Integer) con.newInstance();
System.out.println();
}catch (Exception e){
System.out.println(e);
}
}
4:
public class Hello implements Cloneable{
public void sayHello(){
System.out.println("hello !");
}
public static void main(String args[]){
Hello h1 = new Hello();
try{
Hello h2 = (Hello) h1.clone();
h2.sayHello();
}catch(Exception e){
System.out.println(e);
}
}
}
5:反序列化来创建对象
FileInputStream in1 = new FileInputStream(f);
ObjectInputStream oos = new ObjectInputStream(in1);
16. 重载 重写
17. equals 和 hashcode
简单来说,可以这样理解:hashcode的相等是equals为true的前提。hashcode相等,equals不一定为真,但是equals为真,那么hashcode一定相等
18.hashcode 和 equals一起重写
HashMap中,key的比较是两个都要比较,先比较hashcode,再比较equals。两者都是继承自父类。追根结底是要比较地址。若两者不一起重写,当比较equals()时只是看他们是否为同一对象(即进行内存地址的比较),所以必定要两个方法一起重写。