最后
针对以上面试题,小编已经把面试题+答案整理好了
面试专题
除了以上面试题+答案,小编同时还整理了微服务相关的实战文档也可以分享给大家学习
4.7.2 垃圾回收器【自动垃圾回收机制、GC机制】
什么时候考虑将某个java对象的内存回收呢?
1)当栈内存当中java对象称为垃圾数据的时候,会被垃圾回收器回收;
2)什么时候堆内存的java的对象会变成垃圾呢? -没有更多的引用指向它的时候;
-这个对象无法被访问,因为访问对象只能通过引用的方式访问;
4.8 空指针异常
public class Code{
public static void main(String[] args){
Customer c = new Customer();
System.out.println(c.id);
c=null;
//以下程序编译可以通过,因为符合语法, //运行出现空指针异常
//空引用访问“实例”相关的数据一定会出现空指针异常
//java.lang.NullPointerException
System.out.println(c.id);
}
}
4.9 关联关系和继承关系
关联关系:A has a B【A对象中含有B对象的引用】;
继承关系:A is a B【关系更加紧密】;
5、封装
====
5.1 封装的好处
1)封装之后对于那个事物来说,看不到这个事物比较复杂的那一面,只能看到该事物简单的那一面,复杂性封装,对外提供简单的操作入口;
2)封装之后才会形成真正的"对象",真正的"独立体";
3)封装之后意味着以后的程序可以重复使用,并且这个事物适应性比较强,在任何场所都能够使用;
4)封装之后,对于事物本身提高了安全性;
5.2 如何封装
1)属性私有化
使用private关键字进行修饰,修饰的所有数据只能在本类中访问;
2) 对外提供简单的操作入口(两个公开的方法)
-调用set方法:修改属性;
-调用get方法:读取属性;
3)set方法的命名规范
public void setAge(int a){
//编写业务逻辑代码进行安全控制 if()
age = a;
}
由于java有就近原则,以下代码Error
public void setAge(int age){
age = age;
}//这里并没有给age属性赋值,这里的age都是局部变量age
4)get方法的命名规范
public int getAge(){
//编写业务逻辑代码进行安全控制 if()
return age;
}
而在eclipse中get和set方法不用写,直接按下面操作自动生成get,set方法
单击右键—>Source—>Generate Getters and Setters
5.3 封装后如何访问
调用方法:
修改:user.setAge(-100);
读取:user.getAge();
注意:不能通过"类型.变量名"访问,已经封装在类中,外部无法访问,只能通过方法;
6、构造方法
======
6.1 定义
构造方法又被称为构造函数/构造器/Constructor
6.2 构造方法的语法结构
[修饰符列表] 构造方法名 (形式参数列表){
构造方法体;
}
与普通方法的语法结构对比:
[修饰符列表] 返回值类型 方法名(形式参数列表){
方法体;
}
注意:
1)"返回值类型"不需要指定,也不用写void;
写上void就变成了普通方法了;
2)构造方法名必须与类名相同;
6.3 构造方法的调用
1)普通方法的调用:
方法修饰符有static时:类名.方法名(实参列表);
方法修饰符没有static时:引用.方法名(实参列表);(需要先创建对象)
2)构造方法的调用: new 构造方法名(实参列表);
3)构造方法执行之后有返回值,且返回值类型为构造方法所在类的类型(他本身),所以语法结构中不用写返回值类型,构造方法执行之后java程序自动返回值;
4)当一个类中没用定义任何构造方法的话,系统默认给该类提供一个无参数的构造方法,这个构造方法被称为缺省构造器;
5)当一个类显示的将构造方法定义出来了,那么系统不再默认提供的缺省构造器了,建议开发中手动的为当前类提供无参数的构造方法;
6)构造方法支持重载机制,在一个类中编写多个构造方法,这多个构造方法显然已经构成方法重载机制;
public class Code{
public static void main(String[] args){
User u1 = new User(“Jack”);
User u2 = new User(10);
}
}
public User(int i){
System.out.println(“带有int参数类型的构造器”)
}
public User(String name){
System.out.println(“带有String参数类型的构造器”)
}
6.4 方法有无static方法的调用
方法有static修饰时,调用方法时不需要new对象,直接通过方法名(实参)/类名.方法名(实参)调用;
public class Code{
public static void main(String[] args){
Code.dosome();
dosome;
}
}
public ststic void dosome(){
System.out.println(“do some”);
}
方法没有static修饰时,调用方法时需要new对象;
public class Code{
public static void main(String[] args){
Code t = new Code();
t.dosome;
}
}
public void dosome(){
System.out.println(“do some”);
}
6.5 构造方法的作用
1)创建对象;
2)初始化实例变量的内存空间,赋值;
注意: 实例变量的系统默认赋值不是在类加载的时候完成赋值的,类加载的时候只将代码片段加载到了方法区内存,而实例变量的初始化是在创建对象之后(构造方法完成之后)完成初始化的
6.6 自动构造方法的快捷方式
单击右键—>Source—>Generate Constructor using Fields…
6.7 面向对象的封装以及构造方法的实例
public class helloworld{
public static void main(String[] args){
Bank b = new Bank(“Jack”,1000);
System.out.println(“账号名字为” + b.getName());
System.out.println(“账号余额为” + b.getMoney());
Bank a = new Bank();
System.out.println(“账号名字为” + a.getName());
System.out.println(“账号余额为” + a.getMoney());
}
}
class Bank{
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
private String name;
private int money;
//无参数的构造器
public Bank(){
}
//有参数的构造器
public Bank (String s,int d) {
name = s;
money = d;
}
}
7、this关键字
=========
7.1 this关键字的定义和性质
1)this是一个关键字 / 引用 / 变量,this变量中保存了内存地址表示自身,this存储在JVM堆内存java对象内;
2)创建100个java对象,每一个对象都有this,也就是说有100个不同的this;
3)this可以出现在“实例方法”当中,this指向当前正在指向这个动作的对象。【this代表当前对象】;
4)this在多数情况下都是可以省略不写的;
5)this在区分局部变量和实例变量的时候,"this."不能省;
public void setName(String name) {
this.name = name;
}
//“=”前面的this.name是实例变量
//“=”前面的name是局部变量,是形式参数
6)this不能使用在带有static的方法当中;
7.2 实例方法与实例变量
7.2.1 实例方法的访问(不带static的方法)
public class helloworld {
public static void main(String[] args) {
// 创建Customer对象
Customer c1 = new Customer();
c1.name = “zhangshan”;
// c1购物
c1.shopping();
// 创建Customer对象
Customer c2 = new Customer();
c2.name = “lisi”;
// c2购物
c2.shopping();
}
}
class Customer {
// 姓名
String name;
// 构造方法
public Customer() {
}
//实例方法
public void shopping(){
//当张三在购物的时候输出"张三在购物"
//当李四在购物的时候输出"李四在购物"
System.out.println(this.name + “在购物”);
}
}
7.2.2 实例变量的访问(不带static的变量)
public class helloworld {
public static void main(String[] args) {
//访问"当前对象"的num属性
//System.out.println(num); //编译错误(因为num是一个实例变量,需要"引用."的方式访问)
//如何访问num?
//创建一个对象
ThisTest tt = new ThisTest();
System.out.println(tt.num);
}
}
class ThisTest{
//实例变量
int num = 10;
}
7.3 静态方法
1)静态方法(带有static的方法)访问的时候采用 类名.方法名,不能用this;
2)静态方法中不能"直接"访问实例变量和实例方法;(实例变量和实例方法都需要对象的存在);
3)静态方法中没有this,也就是说"当前对象"不存在,自然也无法访问当前对象的实例变量和实例方法(this代表的是当前正在执行这个动作的对象);
4)静态方法,既可以采用类名的方式访问,也可以采用应用的方式访问,但是即使采用引用的方式访问,实际上执行的时候和引用指向的对象无关,还是默认成“类名.”的方式访问,且会产生警告,但不会产生空指针异常;
7.4 特例:实例方法中实例方法的访问
实例方法和静态方法的访问的比较
public class ThisTest{
public static void main(String[] args){
//ThisTest.doSome();
//编译错误(实例方法必须先创建对象,通过引用.的方式访问)如下:
ThisTest tt = new ThisTest();
tt.run();
doSome();//带有static的方法,可以通过类名.的方式直接访问
}
public static void doSome(){
System.out.println(“do some!”);
}
public void doOther(){
System.out.println(“do other”);
}
//特例:实例方法中实例方法的访问
public void run(){
System.out.println(“run execute!”);
doOther();//this.doOther
//这里可以直接写“doOther();”由于是通过run()来访问到doOther的,此时this就是访问run()时的对象
}
}
7.5 实例方法和实例变量的定义和访问的比较
不带有static关键字的方法被称为"实例方法";
不带有static关键字的变量被称为"实例变量";
public class ThisTest{
public static void main(String[] args){
//编译错误
/*System.out.println(name);
doSome();
System.out.println(this.name);
this.doSome();*/
//编译通过
ThisTest tt = new ThisTest();
System.out.println(tt.name);
tt.doSome();
}
//实例变量
String name;
//实例方法
public void doSome(){
System.out.println(“do some!”);
}
}
7.6 this的作用领域
1)可以使用在实例方法中,代表当前对象【语法格式:this】
2)可以使用在构造方法中,通过当前的构造方法调用其他的构造方法【语法格式:this(实参)】;
3)this()这种语法只能出现在构造方法的第一行;
使用在构造方法中,通过当前的构造方法调用其他的构造方法的代码如下:
public class helloworld {
public static void main(String[] args) {
Date d = new Date();
System.out.println(d.getYear() + “-” + d.getMonth() + “-” + d.getDay());
Date a = new Date(2021,1,3);
System.out.println(a.getYear() + “-” + d.getMonth() + “-” + d.getDay());
}
}
class Date{
private int year;
private int month;
private int day;
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public Date() {
//需求:当程序员调用以下无参数的构造方法的时候,默认创建日期为1970.1.1
/*this.year = 1970;
this.month = 1;
this.day = 1;*/
//以上代码可以通过调用另一个构造方法来完成
//但前提是不能通过创新新的对象。以下代码表示创新了一个新的对象
//new Date(1970.1.1);
//需要采用以下的语法来完成构造方法的调用
this(1970,1,1);
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
}
7.7 两种方法调用 以及 实例变量的访问 的完整/省略写法
public class Test{
//没有static的变量
int i = 10;
//带有static的方法
public static void doSome() {
System.out.println(“do some!”);
}
//没有static的方法
public void doOther() {
System.out.println(“do other!”);
}
//带有static的方法
public static void method1() {
//调用doSOme(带有static的方法)
//完整方法的调用
Test.doSome();
//省略方法的调用
doSome();
//调用doOther(没有static的方法)
//完整方法的调用
Test t = new Test();
t.doOther();
//省略方法的调用
//无
//访问i(实例参数)
//完整方法的调用
System.out.println(t.i);
//省略方法的调用
//无
}
//没有static的方法
public void method2() {
//调用doSOme(带有static的方法)
//完整方法的调用
Test.doSome();
//省略方法的调用
doSome();//this doSome();
//调用doOther(没有static的方法)
//完整方法的调用
this.doOther();//调用的doOther中无static,且当前方法中也无static,当前方法有this,所以直接引用.即this.doOther()
//省略方法的调用
doOther();
//访问i(实例参数)
//完整方法的调用
System.out.println(this.i);
//省略方法的调用
System.out.println(i);
}
//主方法
public static void main(String[] args) {
//要求在这里编写程序调用method1(带有static的方法)
//完整方法的调用
Test.method1();
//省略方法的调用
method1();
//要求在这里编写程序调用method2(没有static的方法)
//完整方法的调用
Test t = new Test();
t.method2();
//省略方法的调用
//无
}
}
8、static关键字
===========
8.1 static关键字的定义和性质
1)static翻译为"静态的";
2)static修饰的方法是静态方法,static修饰的变量是静态变量;
3)使用static修饰的元素都称为静态的,都可以用"类名."的方式访问,当然也可以用"引用."的方式访问【但不建议】
4)采用"引用."的方式访问的时候,即使引用是null,也不会出现空指针异常,因为访问静态数据不需要对象的存在;
8.2 实例变量与静态变量
8.2.1 实例变量
什么时候成员变量声明为实例变量呢?
–所有对象都有这个属性,但是这个属性的值会随着对象的变化而变化【不同对象的这个属性具体值不同】
–实例变量在构造方法进行的时候初始化,存在堆内存中
以下列例子说明:
public class helloworld {
public static void main(String[] args) {
Chinese zhangsan = new Chinese(“1”,“zhangsan”,“Chinese”);
System.out.println(zhangsan.country);
}
}
class Chinese{
String id;
String name;
String country;
public Chinese(String id, String name, String country) {
this.id = id;
this.name = name;
this.country = country;
}
}
8.2.2 静态变量
什么时候成员变量声明为实例变量呢?
–所有对象都有这个属性,并且所有对象的这个属性的值是一样的,建议定义为静态变量,节省内存的开销
**静态变量在类加载的时候初始化,内存在方法区中开辟。**访问的时候不需要创建对象,直接使用"类名.静态变量名"的方式访问;
补充:
-
局部变量存储在栈内存当中;
-
实例变量在构造方法进行的时候初始化,存在堆内存中
以下列例子说明:
public class helloworld {
public static void main(String[] args) {
Chinese zhangsan = new Chinese(“1”,“zhangsan”);
System.out.println(zhangsan.country);
System.out.println(Chinese.country);
zhangsan = null;
System.out.println(zhangsan.country);
}
}
class Chinese{
String id;
String name;
static String country = “chinese”;
public Chinese(String id, String name) {
this.id = id;
this.name = name;
}
}
输出结果为三个Chinese;
1)所有静态的数据都是可以采用"类名.“,也可以采用"引用.”,但是建议采用类名.的方式访问;
2)采用"引用."的方式访问时,即使是null,也不会出现空指针异常,因为访问静态变量的时候不需要对象的存在;
8.3 静态代码块
1)语法格式:
static{
//java语句
}
2)静态代码块在类加载时执行,并且执行一次;
3)静态代码块在一个类中可以编写多个,并且遵循自上而下的顺序依次执行;
4)静态代码块可以用在项目中要求在类加载的时刻/时机执行代码完成日志的记录,那么这段记录日志的代码就可以编写在静态代码块当中,完成日志记录;
5)静态代码块是java为程序员准备一个特殊的时刻,这个时刻被称为类加载时刻,若希望在此刻执行一段特殊的程序,这段代码可以放到静态代码块当中;
public class StaticTest{
static{
System.out.println(“类加载—>1”);
}
static{
System.out.println(“类加载—>2”);
}
}
8.4 *实例语句块 / 代码块
1)实例代码块可以编写多个,也是遵循自上而下的顺序依次执行;
2)实例代码块在构造方法执行之前执行,构造方法执行一次,实例代码块对应执行一次;
3)实例代码块也是java语言为程序员准备一个特殊的时机,这个时机被称为:对象初始化时机;
public class helloworld{
public class Test{
//构造函数
public Test(){
System.out.println(“Test类的缺省构造器执行”);
}
}
//实例代码块
{
System.out.println(1);
}
//实例代码块
{
System.out.println(2);
}
public static void main(String[] args){
System.out.println(“main begin”);
new helloworld();
}
}
8.5 static总结
public static void main(String[] args)
8.5.1 对java语句的解读
1)public代表公开的,在任何位置都可以访问;
2)static表示静态的,使用"类名."的方式访问,不需要创建对象
3)void表示main方法执行结束之后不返回任何值;
4)(String[] args)是参数列表;
8.5.2 什么时候定义为静态的?
1)方法描述的是动作,当所有的对象执行这个动作的时候,最终产生影响是一样的,那么这个动作已经不再属于某一个对象动作了,可以将这个动作提升为类级别的动作,模板级别的对象;
2)静态方法中无法直接访问实例变量和实例方法;
3)大多数方法都定义为实例方法,一般一个行为或一个动作在发生的时候都需要对象的参与而大多数“工具类”当中的方法都是静态的,因为工具类就是方便编程的,为了方便方法的调用,自然不需要new对象是最好的;
9、继承
====
1)继承是面向对象的三大特征之一,三大特征分别是:封装、继承、多态;
2)继承"基本"的作用是,代码复用。最重要的作用是:有了继承之后才有的"方法的覆盖"和"多态机制";
3)继承语法格式:
[修饰符列表] class 类名 extends 父类名字{
类名 = 属性 + 方法;
}
4)java语言当中的继承只有单继承,一个类不能同时继承很多类,只能继承一个类。在C++中支持多继承;
5)关于继承中的一些术语:
B类继承A类,其中:
A类称为:父类、基类、超类、superclass;
B类称为:子类、派生类、subclass;
6)java语言中能继承父类的哪些数据?
-
私有的不支持继承;
-
构造方法不支持继承;
-
其他数据都有被继承;
7)虽然java语言当中只支持单继承,但是一个类也可以间接继承其他类,例如:
C extends B{
}
B extends A{
}
A extends T{
}
//C直接继承B类,但是C类间接继承T、A类;
8)java语言中假设一个类没有显示继承任何类,该类默认继承JavaSE库中提供的java.lang.ob.jact类;
public class helloworld{
public static void main(String[] args){
C c = new C();
c.doSome();//这里调用的doSome方法是从B类在继承过来的doSome方法
}
}
class A{
public void doSome(){
System.out.println(“do some!”);
}
}
class B extends A{
}
class C extends B{
}
9)eclipse快速继承
10、方法覆盖
=======
1)方法覆盖又称为方法重写(override【官方的】/overwrite)
2)什么时候使用方法重写?
-
当父类中的方法已经无法满足当前子类的业务需求;
-
子类中有必要将父类中的继承过来的方法进行重新编写;
3)什么条件满足之后会发生方法重写呢?
-
方法重写发生在具有继承关系的父子类之间;
-
方法重写的时候:返回值类型相同,方法名相同,形式参数列表相同;
-
方法重写的时候:访问权限不能更低,可以更高;(指public相关的修饰词)
-
方法重写的时候:抛出异常不能更多,可以更少;
4)注意:
-
私有方法不能继承,所以不能覆盖;
-
构造方法不能继承,所以不能覆盖;
-
静态方法不存在覆盖;
-
覆盖只针对方法,不谈属性;
5)eclipse快速重写
11、多态
=====
11.1 关于java语言中多态语言机制:
1)Animal、Cat、Bird三个类之间的关系:
Cat继承Animal; Bird继承Animal; Cat和Bird之间没有任何继承关系;
2)向上转型(upcasting) 子类型——>父类型(自动转换)
- 编译通过,运行一定可以
向下转型(downcasting) 父类型——>子类型(强制类型转换)【需要加强制类型转换符】
- 编译通过,运行不一定通过,存在隐患
3)无论是向上转型还是向下转型,两者必须要有继承关系;
public class helloworld {
public static void main(String[] args) {
Animal a = new Animal();
a.move();
Bird b = new Bird();
b.move();
Animal a2 = new Bird();//1.1.1关于该语句的解读
a2.move();
//a2.eat(); //1.1.2关于该语句的解读
Bird c2 = (Bird)a2;
c2.eat();
Animal a3 = new Cat();
Bird c3 = (Bird)a3;//1.1.3关于该语句的解读
}
}
class Animal {
public void move() {
System.out.println(“动物会跑”);
}
}
class Bird extends Animal {
//重写父类中继承的方法
public void move() {
System.out.println(“鸟会跑”);
}
//这个方法不是从父类中继承过来的,是子类中特有的行为
public void eat() {
System.out.println(“鸟吃虫”);
}
}
最后
无论是哪家公司,都很重视基础,大厂更加重视技术的深度和广度,面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。
针对以上面试技术点,我在这里也做一些分享,希望能更好的帮助到大家。
- 方法重写的时候:抛出异常不能更多,可以更少;
4)注意:
-
私有方法不能继承,所以不能覆盖;
-
构造方法不能继承,所以不能覆盖;
-
静态方法不存在覆盖;
-
覆盖只针对方法,不谈属性;
5)eclipse快速重写
11、多态
=====
11.1 关于java语言中多态语言机制:
1)Animal、Cat、Bird三个类之间的关系:
Cat继承Animal; Bird继承Animal; Cat和Bird之间没有任何继承关系;
2)向上转型(upcasting) 子类型——>父类型(自动转换)
- 编译通过,运行一定可以
向下转型(downcasting) 父类型——>子类型(强制类型转换)【需要加强制类型转换符】
- 编译通过,运行不一定通过,存在隐患
3)无论是向上转型还是向下转型,两者必须要有继承关系;
public class helloworld {
public static void main(String[] args) {
Animal a = new Animal();
a.move();
Bird b = new Bird();
b.move();
Animal a2 = new Bird();//1.1.1关于该语句的解读
a2.move();
//a2.eat(); //1.1.2关于该语句的解读
Bird c2 = (Bird)a2;
c2.eat();
Animal a3 = new Cat();
Bird c3 = (Bird)a3;//1.1.3关于该语句的解读
}
}
class Animal {
public void move() {
System.out.println(“动物会跑”);
}
}
class Bird extends Animal {
//重写父类中继承的方法
public void move() {
System.out.println(“鸟会跑”);
}
//这个方法不是从父类中继承过来的,是子类中特有的行为
public void eat() {
System.out.println(“鸟吃虫”);
}
}
最后
无论是哪家公司,都很重视基础,大厂更加重视技术的深度和广度,面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,是不是能真的得到锻炼。
针对以上面试技术点,我在这里也做一些分享,希望能更好的帮助到大家。
[外链图片转存中…(img-Z4g5WnCf-1715657254876)]
[外链图片转存中…(img-G9ZSzDTj-1715657254877)]
[外链图片转存中…(img-gfCOVxXo-1715657254877)]