Java一次编写到处运行
JVM(Java虚拟机),源代码(.java)由编译器编译为字节码(.class)。将字节码文件放到各个平台的虚拟机运行。
Java的数据类型
包括基本数据类型和引用数据类型,基本数据类型有,byte,short,int,long,float,double,char,boolean。引用数据类型(类,接口,数组),就是对一个对象的引用,根据引用对象类型的不同进行分类。本质上通过指针,指向堆中对象所持有的内存空间。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q0Emwjuf-1639014037502)(C:\Users\86130\AppData\Roaming\Typora\typora-user-images\image-20211204153047326.png)]
Java语言的编码方案
采用Unicode编码标准,为每一个字符制定了唯一一个数值,在任何的语言、平台、程序都可以放心的使用。
Java的访问权限
三种访问修饰符:private、protected、public
四种访问权限:private、default、protected、public
修饰成员变量/成员方法时,
- private:类内部成员可以访问
- default:类内部成员、同一包下的其他类访问
- protected:类内部成员、同一包下的其他类,他的子类
- public:任一包下的任一类。
修饰类,只能由两种访问权限
- default:同一包下的其他类
- public:任一包下的任一类访问
final、final、finalize的区别
- 被final修饰的类不可继承
- 被final修饰的方法不可重写
- 被final修饰的变量不可被改变(这里改变的是指引用而不是指向的内容)
finally一般是作用于try-catch代码块中,在处理异常时,将一定会执行的代码块放入finally中(一般存放一些关闭资源的代码)
finalize是一个方法,属于Object类的一个方法,Object是所有类的父类,该方法一般由垃圾回收器调用,当我们调用System.gc()方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的最后判断。
this关键字
指向对象本身的指针
super
指向自己父类的指针(这个超类是指的是;离自己最近的父类)
以上两个关键字均不适用于static环境
全局变量和局部变量
全局变量在类的范围内定义的变量,有默认初始值;局部变量是方法里定义的变量。
static的主要意义
是能够没有创建对象也能使用属性、方法,形成静态代码块优化程序性能:只在类加载的时候执行一次。因此很多只需执行一次的初始化操作都放在static代码块中进行。
Java跳出多重循环(ok: break ok;)
为什么要有包装类?
Java设计理念是“一切皆对象”,所有的引用类型的变量都继承于Object类,都可以当做Object类型的变量使用,但基本数据类型却不可以。如果某个方法需要Object类型的参数,但实际传入的值却是数字的话,就需要做特殊的处理了。有了包装类,这种问题就可以得以简化。
自动封装:可以直接将一个基本数据类型的数据赋给对应的包装类型。
自动拆箱:可以把一个包装类型的对象直接赋值给对应的基本数据类型。
Integer与Double如何进行比较?
- 不能用==,因为是不同数据类型
- 不能转化为字符串,浮点数带小数点,整数值不带
- 不能用compareTo方法比较(只能比较相同类型)
- 可以都转化为相同的基本数据类型再进行比较
Integer与int的区别,二者在进行==运算时得到什么结果
二者再进行比较时,Integer会自动拆箱为int在进行比较
封装的目的是什么?为什么会有封装?
隐藏类的实现细节,限制外部对成员变量的访问,可以进行数据检查,有利于保证对象信息的完整性,便于修改提高代码的可维护性。
多态的理解?
Java里面允许把一个子类对象直接赋给一个父类引用变量,无需任何类型转换(向上转型)。
相同类型的变量、调用同一个方法时呈现出多种不同的行为特征就是多态。
继承、重写、将子类对象赋给父类引用,多态的实现方式重写(重写父类的某些方法)、接口、抽象类(实现抽象类/接口的某些抽象方法)。
Java为什么是单继承?
Java在设计时借鉴了C++的语法,C++支持多继承,如果,两个父类包含相同的方法,子类在调用或重写这个方法时就会产生迷惑。Java中的一个类只能有一个直接的父类(可以有多个间接的父类)。
重载和重写的区别?
重载只能发生在一个类中,方法名相同、参数列表不同。(重载的方法不能根据返回值进行区分)。重写,重写发生在子类和父类之间,方法名必须和父类方法一致,返回值、异常要小于等于父类方法,访问权限要大于父类方法。
构造方法可不可以重写?
构造方法不能重写。构造方法要求与类名保持一致,如果子类可以重写构造方法,意味着,子类中必然出现与其类名不相同的构造方法,这与构造方法的要求显然是矛盾的。
Object类中的方法
Class<?>getClass:返回对象运行时的类。
boolean equals(Object obj):判断指定对象与该对象是否相等。
int hasCode():返回该对象的hasCode值:类似于哈希?
String toString():返回可以表述该对象信息的字符串
wait()、notify()、notifyAll()控制线程的暂停与运行,clone()获得当前对象的副本(被protected修饰)、finalize()垃圾回收方法
hasCode()和equals()
hasCode用于获得哈希码,equals用于比较两个对象是否相等。
两个对象相等必须有一样的哈希码,两个对象有相同的哈希码,未必相等
==和equals()
==作用于基本运算符时,比较两个数值是否相等,作用于引用数据类型时比较两个对象的内存地址是否相同,判断他们是否为同一对象。
equals()没有重写时,Object默认用==实现,比较内存地址是否相同,进行重写之后,按照内容进行比较
String、StringBuffer和StringBuilder的区别
String是不可变类,由final修饰,不可被继承,不可被修改。一个String对象一旦被创建,不可被改变,直至被销毁。
StringBuffer对象代表字节序列可以改变的字符串,可以通过自带的方法如(append、setCharAt)来改变字符串序列。如果生成了最终想要的字符串,可以调用toString()方法将其转化为String对象。
StringBuilder和StringBuffer都代表着可变的字符串对象,并且他们都具有相同的父类,构造方法与成员方法基本相同。不同的是StringBuffer线程安全,一般优先考虑。
使用字符串时,new和“”更推荐哪种方式?
采用new的方式回多创建一个对象出来,占用更多内存,一般使用直接量的方式创建字符串。
字符串拼接的方式
“+”:要求拼接的都是字符串常量,在编译器编译时直接会优化成为一个完整的字符串。StinrBuffer要求线程安全,底层采用append()方法实现。concat方法拼接两个字符串时效率高。
字符串String a = "abc";
,说一下这个过程会创建什么,放在哪里?new String("abc")
是去了哪里,仅仅是在堆里面吗?
JVM使用常量池来管理字符串直接量,会先检查常量池,if(1)赋给a,else先将“abc”存入常量池,再进行赋值;在执行的时候,会先将abc存入常量池,再在堆内存中创建String对象,最后再将堆内存中变量a指向常量池中变量“abc”。
接口和抽象类的区别
设计的目的上,二者的区别:
接口本质上是一种规范,对于实现者而言,规定了必须向外提供哪些服务,对于调用者来说规定了可以调用哪一部分功能。是多个程序之间通信的标准。抽象类是一种模板设计,是系统实现过程中的中间产品。
接口(can)、抽象类(is-a)
接口只能包含抽象方法,静态方法,默认方法和私有方法,不能为普通方法提供方法实现,抽象类包含普通方法。都不能被实例化。
接口中不能包含构造器和初始化块定义,只能定义静态变量。
一个类只能有一个直接父类包括抽象类,但是一个类可以实现多个接口,通过接口可以弥补Java单继承的不足。
通过对接口的使用可以很好的降低程序各模块之间的耦合,提高系统的可扩展性和可维护性。
处理异常的方式
try-catch-finally
将业务代码封装进try块内部,发生任何异常都会创建一个异常对象,将此异常对象交给catch块处理。
catch先记录日志,根据异常类型,结合业务情况进行相应处理。
打开了某个资源,比如数据库连接等,无论是否发生异常,都需要执行的代码块可以放在finally中
抛出异常:当判断某项错误的条件成立时可以使用throw向外抛出异常,不知道如何处理时,可以使用throws关键字抛出异常交由JVM处理
Finally语句块总会执行,注意Finally代码块中不要使用return,throw等使程序终止