JAVA_基础

一.谈谈你对面向对象的理解

面向过程和面向对象是 两种不同的处理问题的角度

  • 面向过程:注重事情的每一个步骤以及顺序        直接高效
  • 面向对象:注重事情的参与者,各自需要做什么    易于"扩展""维护""复用"
  • 三大特性:
    •  封装: 类只提供外部调用的接口,外部调用无需关注内部是如何实现的
      • 体现:
        • 属性私有化,提供get和set方法
        • orm框架:操作数据库,不用管如何链接的,只需要映入mybatis,调用方法即可
        • 单例模式
    • 继承:子类继承父类,使用父类中的属性和方法,并可以扩展
    •  多态: 条件: 继承,方法重写,父类引用指向子类对象,调用子类的方法,表现出子类的不同形态
      • 缺点:无法使用子类特有的方法
二.JDK和JRE和JVM的关系和区别

  • jdk:jre+开发工具集
  • jre:java运行环境 jvm+核心类库
  • 简单而言:使用jdk开发java程序,交给jre运行
三.==和equals( )的区别
  •  ==: 关系运算符
    • 引用类型比较的是地址(栈中存放的地址值)
    • 基本数据类型比较的是
    • 不能比较没有父子关系的两个对象
  • equals: 方法
    • 比较的是内容,但是Object默认的equal方法就是使用==,所以需要重写equal。
    • 一般还需要重写hashCode ().系统类(比如String类)已默认重写了equal。
    • 注意:使用equals把常量写在前面,因为使用object的equals object可能为null 则空指针。
四.什么是装箱?什么是拆箱?装箱和拆箱的执行过程?常见问题?
  • 装箱:基本类型转变为包装类的过程。 调用包装类.valueOf()
  • 拆箱:包装类转变为基本类型的过程。 调用包装类.xxxValue()。如intValue(new Integer(1))
  • 常见问题:整型有缓存
    • 整型的包装类valueOf方法返回对象时,在常用的取值范围内( -128 ~ 127 ),JVM会返回缓存对象。
    • 浮点型的包装类 valueOf 方法返回新的对象。
    • 布尔型的包装类 valueOf 方法 Boolean类的静态常量 TRUE | FALSE。
int i = 100;
Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;
System.out.println(i == i1);//true (一方妥协,引用类型变为基本类型)
System.out.println(i1 == i2);//true (缓存)
System.out.println(i3 == i4);//false 
 五.final

final在java中的作用?

  • 修饰,不能被继承;
  • 修饰方法,不能被重写;
  • 修饰属性,必须赋初始值,不能被修改。
    • 修饰基本属性,值不能变;修饰引用属性,栈中的引用不能变,引用指向的对象可变。

final finally finalize()区别?

  • finally:try -catch-finally中使用,表示必须执行的语句。
  • finalize():对象被回收时调用的方法。一般情况下,此方法由JVM调用,用来释放一些资源。

finally语句块一定执行吗?

  • 不一定。
  • 没有执行到try中的代码,肯定不会执行finally中的方法。 (比如程序中途return 或者抛出异常半路终止,都没有执行到try中,但如果执行到try中,就一定会执行finally)
  • 执行到try中的方法,JVM半路终止,使用System.exit(0);
 六.static
  • 可以修饰属性方法的时候,表示该属性/方法是属于类的,随着类的加载而加载。
  • JVM加载类的时候,就会执行该代码,只会执行一次。修饰的属性可以重新赋值。
七.抽象类/方法

  • 抽象类不能被实例化,抽象方法只需声明,无需实现。
  • 抽象方法不能声明为final,private,static.
  • 具有抽象方法的类一定是抽象类,抽象类不一定有抽象方法。

接口中可以定义:

  • jdk8之前:全局常量,抽象方法(可省略public  abstract)
  • jdk8之前:多了默认方法和静态方法

抽象类和接口的关系?

  • 语法层面:
    • 同:都不能被实例化
    • 抽象类:有构造器;可以有普通成员变量;方法也不一定都是抽象的。
    • 接口:无构造器;只能有全局常量,没有普通成员变量;jdk8前都是抽象方法,jdk8后多了两种方法。
  • 设计层面:
    • 抽象类是为了代码复用,把一些类的公共部分抽取出来。
    • 接口是对类的行为进行约束。 
八.java访问修饰符?  
  • public:同一工程下
  • protected:不同包下的子父类
  • 缺省:同一包下
  • private:同一类中
九.异常

处理异常的方式?

  • try-catch-finally
  • throws+异常类型:

手动抛出异常: throw new RuntimeException()

try-catch-finally中哪个部分可以省略?

  • catch 和 finally 语句块可以省略其中一个
十.内部类

内部类:既有类的特性又有外部类成员的特性

分类:

  • 成员内部类(静态/非静态):class Test{ class AA{} }
  • 局部内部类:声明在方法内,常用于匿名内部类的使用

 

class Test{
    public Comparable methods(){
        //Comparable 是一个接口,相当于创建了一个接口的实现类并返回。
        return new Comparable() {
            @Override
            public int compareTo(Object o) {
                System.out.println("123");
                return 0;
            }
    };
    }
}

使用内部类的好处?

  • 封装:将一些特性作为类的成员进行封装 ,比如:人类和大脑类
  • 内部类拥有外部类的所有元素的访问权限
  • 多重继承的解决方案,弥补了Java类是单继承的不足     

注意: 内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件

十一:反射

什么是反射?

  • 体现java的动态性,根据字节码文件
  • 在运行状态中,只要给定类的名字,就可以通过反射机制来获得类的所有信息 (包括属性,方法,类型,注解等)。
  • 可以调用类的任何对象的方法/属性,动态创建对象等

获得Class对象的方法?

  • Class c = 类名.class
  • Class c = 对象名.getClass()
  • Class c = Class.forName("类的全路径")

反射的作用?

  • 可以实现动态装配,降低代码的耦合度
  • JDBC原生代码注册驱动;动态代理(aop)都使用到反射。
  • spring中定义的注解,就是通过反射查找出来的
十二.克隆

就是堆空间中克隆出一个对象,拥有相同的属性和方法。

如何实现克隆?

  1. 需要克隆的类实现Cloneable接口(标记接口),重写 clone()方法(Object的方法)。
  2. 对象调用clone()完成克隆。

什么是浅克隆,什么是深克隆?

  • Object中的clone()是浅克隆,只能克隆基本数据类型的属性,对于引用类型的属性就只是指向之前的对象。
  • 如果需要深克隆(引用类型的属性也克隆一份),就需要手动修改clone()。

实现深克隆?

  • 重写clone方法
@Override
protected Person clone() throws CloneNotSupportedException {
    //使用object的clone()先克隆一份对象
    Person p = (Person) super.clone();
    //将对象中的引用属性重新进行克隆
    p.setDog((Dog) p.getDog().clone());
    return p;
}
  • 序列化   

什么场景要对象克隆?

  • 方法需要 return 引用类型,但又不希望自己持有引用类型的对象被修改。
  • 程序之间方法的调用时参数的传递。有些场景为了保证引用类型的参数不被其他方法修改,可以使用克隆后的值作为参数传递。
十三.重载和重写的区别?
  • 重载:发生在本类,同名不同参(参数类型、个数、顺序),与方法的返回值无关
  • 重写:发生在子父类,同名同参,方法返回值范围小于等于父类的,抛出异常范围小于等于父类的,访问权限修饰符大于等于父类的
十四.代码块的执行过程?
  •  父类静态代码块
  • 子类的静态代码块
  • 父类的构造代码块
  • 父类的构造方法
  • 子类的构造代码块
  • 子类的构造方法
十五.创建对象的几种方式?
  • new
  • 反射,Class对象.newInstance()
  • object的clone()
  • 反序列化
十六.序列化?
  • 序列化:将对象转变为字节流
  • 反序列化:将字节流转变为对象

什么情况下需要序列化?

  • 当Java对象需要在 网络上传输 或者持久化 存储到文件中 时,就需要序列化。

可序列化对象为什么要定义serialversionUID值?

  • 序列化版本控制,序列化时将类的serialVersionUID写入到序列化文件中,当反序列化时系统 会去检测文件中的serialVersionUID,判断它是否与当前类的serialVersionUID一致, 如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。
十七.Java属于编译型还是解释型语言?

java是半解释型半编译型的语言,主要因为java的执行引擎中采用 解释器JIT编译器(及时编译器)并存的架构

一般步骤:高级语言->汇编语言->机器语言
因为JAVA加入了字节码文件,所以java的流程为:
    高级语言->字节码文件->汇编语言->机器语言
         前端编译   后端编译/解释 
  • 解释器:对字节码指令进行逐行翻译,翻译成本地的机器指令
  • JIT及时编译器:明确,它也可以将字节码转变为本地的机器语言。
    • 但是它转换的是热点代码。对于这些代码,是被重复使用的。JIT就可以高效的执行这些代码。 因为这些代码第一次被转换成机器码之后,后来执行就是执行对于的机器码,速度非常快。

既然HotSpot中已经有了JIT,为什么还要使用效率低的解释器?

  • 当程序启动的时候,解释器可以马上发挥作用,立即执行。JIT不行。
  • JIT要想发挥作用,先得把代码转换为机器指令后,再次执行才发挥作用, 第一次将所有的代码转换为机器指令,就需要很大的时间。
  • 所以,采用并存的方式 。当JVM启动的时候,解释器先发挥作用,就不必等待JIT全部编译完再执行。对于一些热点代码, JIT就可以发挥作用了。整体提高执行的效率。

热点代码? 一个被多次调用的方法或者一个循环体都可以称为热点代码

热点探测方式

  • 基于计数器的探测方式:方法调用计数器 回边计数器
  •  HotSpot会为每一个方法设置这两个计数器;分别记录 方法调用的次数方法内循环体的次数, 当这两个计数器到达一定的阈值时,就会被认定为热点代码。   
十八.时间

java.sql.Date和java.util.Date的区别?

  • util是sql的父类
  • util是jdk的时间, "年月日 时分秒"
  • sql是数据库中Date对应的类型, "年月日"
  • 数据库中如果需要设置"年月日时分秒",可以使用timestamp的类型,对应java.sql.Timestamp
关于时间的函数?
(1)System.currentTimeMillis();   时间戳
(2)new Date();
(3)Calendar calendar = Calendar.getInstance();
    calendar.get(Calendar.YEAR);     //获得时间
    calendar.set(Calendar.YEAR,2021) //设置时间
(4)LocalDateTime.now();    //当前时间
    LocalDateTime.of(2021,9,10,16,38,12);//指定时间   
    
格式化时间?
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
sdf.format();   //时间转变为字符串
sdf.parse();   //字符串转变为时间 
 十九.泛型

 什么是泛型?

  • 类型参数化,将数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中。

 为什么要用泛型?

  • 避免强制转换,具有更好的安全性和可读性。java.lang.ClassCastException 异常
  • 代码的复用,多种数据类型执行相同的代码使用泛型可以复用代码。 比如集合

 

寄语:改变,永远不嫌晚。无论你是几岁,也无论你目前所处的境况有多糟,只要立定目标、一步一步往前走,人生随时都有翻盘的可能性。

posted @ 2021-12-05 20:53  小猴子_X  阅读(70)  评论(0编辑  收藏  举报