112、Java基础汇总

目录

JDK、JRE、JVM?

机器码和字节码的区别?

八大基本数据类型以及它们对应的引用数据类型?

讲一下自动装箱和自动拆箱?

重载和重写的区别?

面向对象和面向过程的区别?

面向对象的三大特征是什么?

接口和抽象类的共同点和区别?

浅拷贝、深拷贝、引用拷贝?

Object类的常见方法有哪些?

==和equals的区别?

hashCode有什么用?

为什么重写equals方法时必须重写hashCode方法?

String、StringBuffer、StringBuilder的区别?

String为什么是不可变的?

字符串常量池了解吗?

Integer常量池的大小?

Java的异常结构?

Checked Exception和Unchecked Exception的区别?

ClassNotFoundException和NoClassDefFoundError的区别?

泛型是什么?

反射是什么?

API和SPI的区别?

静态代理和动态代理的区别?

值传递和引用传递的区别?

static和final的区别?

Java8的新特性主要有哪些?


 

Java语言的特点?

面向对象、跨平台、支持多线程、具备异常处理机制和自动内存管理机制、支持网络编程。

JDK、JRE、JVM?

JDK是Java开发工具包,包含了JRE和编写Java程序所需要的工具,比如javac、javadoc、javap等等。JRE是Java运行时环境,包含了运行已编译Java程序所需要的全部内容,主要包括JVM和Java基础类库。JVM是Java虚拟机,是解释和执行Java字节码的地方。

机器码和字节码的区别?

机器码是计算机能直接执行的二进制指令。而字节码是JVM能解释执行的中间代码,也就是扩展名为.class的文件。

八大基本数据类型以及它们对应的引用数据类型?

基本数据类型占用字节数引用数据类型
byte1Byte
short2Short
int4Integer
long8Long
float4Float
double8Double
char2Character
boolean1或4

Boolean 

 

 

 


 

 

 

 

 

 

如果boolean是单独使用,则boolean占4个字节。
如果boolean是以boolean数组的形式使用,则boolean占1个字节

讲一下自动装箱和自动拆箱?

自动装箱是将基本数据类型自动转换成对应的引用数据类型,其实就是调用了引用类的valueOf()方法,比如Integer.valueOf()方法。

自动拆箱是将引用数据类型自动转换成对应的基本数据类型,其实就是调用了引用类的value()方法,比如Integer.intValue()方法。

重载和重写的区别?

重载指的是在同一个类中,可以定义多个名称相同但参数列表不同的方法,这些方法根据参数的类型、顺序或数量的不同,可以执行不同的操作。

重写指的是子类重新定义父类中已有的方法,可以用来改变或扩展父类的行为,重写方法具有相同的方法名和参数列表,需要在子类中使用@Override注解来明确指出该方法是重写父类方法。

注:如果父类的返回类型是void或基本数据类型,子类必须相同,如果是引用数据类型,子类<=父类的返回类型;子类>=父类的访问权限;子类<=父类抛出的异常;不能重写私有方法。

面向对象和面向过程的区别?

面向对象是将问题领域中的实体抽象成对象,通过对象之间的合作来解决问题。

面向过程是将解决问题的过程拆成一个个方法,通过一个个方法的执行来解决问题。

面向对象的三大特征是什么?

分别是封装、继承、多态。

封装指的是把一个对象的状态信息隐藏在对象内部,不允许外部对象直接访问对象的内部信息,但是可以提供一些能被外界访问的方法来操作内部信息。

继承允许一个类从另一个类上继承属性和方法。子类继承父类并在父类的基础上进行修改和扩展,提高了程序的可维护性。

多态顾名思义,表示一个对象具有多种状态,具体表现为父类的引用指向子类的实例。

接口和抽象类的共同点和区别?

共同点是都无法被实例化,都可以包含抽象方法,都可以使用default关键字来定义具有默认实现的方法。

区别主要有三点。第一点,接口主要用于对类的行为进行约束,一个类实现了某个接口就具有对应的行为。而抽象类主要用于提高代码的复用性,强调的是所属关系。

第二点,一个类只能继承一个抽象类,但是可以实现多个接口。

第三点,接口中的成员变量默认都是public static final类型的,不能被修改并且必须有初始值。而抽象类的成员变量默认是default类型的,可以在子类中被重新定义,也可以被重新赋值。

注:接口中的方法默认都是public abstract类型的。

浅拷贝、深拷贝、引用拷贝?

浅拷贝会在堆上创建一个新对象,但如果原对象内部的属性是引用类型的话,浅拷贝只会复制内部对象的引用地址,也就是说原对象和拷贝对象共用一个内部对象。

深拷贝也会在堆上创建一个新对象,但深拷贝会完全复制整个原对象,包括原对象所包含的内部对象。

引用拷贝不会创建新对象,它只会复制原对象的引用地址。

Object类的常见方法有哪些?

equals、hashCode、toString、getClass、clone、wait、notify、notifyAll

==和equals的区别?

我先说下==,对于基本数据类型,==比较的是值。对于引用数据类型,==比较的是对象的内存地址。我再说下equals,equals不能用来比较基本数据类型,只能用来比较引用数据类型,如果类没有重写equals方法,则比较的是对象的内存地址,如果类重写了equals方法,一般比较的是两个对象的属性值是否相同,如果相同则返回true,比如String类的equals方法就是重写过的,它比较的是字符串内容而不是对象的内存地址。

hashCode有什么用?

hashCode是用来获取哈希码的,也称为散列码,哈希码可以用来确定该对象在哈希表中的索引位置。

为什么重写equals方法时必须重写hashCode方法?

因为我们要保证equals方法判断两个对象相等时,这两个对象的hashCode值也要相等。如果重写 equals方法但没有重写hashCode方法的话,就可能会导致equals方法判断相等的两个对象,它俩的hashCode值却不相等。

String、StringBuffer、StringBuilder的区别?

String是不可变的,每次对String类型的数据进行修改时,都会创建一个新的String对象,它是线程安全的。

StringBuffer和StringBuilder都继承自AbstractStringBuilder类,它俩都是可变的,都可以通过toString方法转换为String类型的对象。StringBuffer是线程安全的,因为它对方法的调用加了同步锁。而StringBuilder没有加锁,所以它是非线程安全的,不过也正因为没有加锁,所以StringBuilder的性能比StringBuffer要更高。

再说下使用场景,String适用于操作少量的数据,StringBuffer适用于多线程环境下操作大量的数据,StringBuilder适用于单线程环境下操作大量的数据。

String为什么是不可变的?

因为String类源码中的字符数组是被private final修饰的,并且Stirng类并没有暴露修改这个字符数组的方法,这意味着我们不能修改String对象内部的字符数组。还有就是String类自己是被final修饰的,这意味着它不能被子类继承和修改,进一步确保了String对象的不可变性。

字符串常量池了解吗?

字符串常量池是JVM为了提升性能和减少内存消耗,专门针对String类开辟的一块区域,主要是为了避免字符串的重复创建。

Integer常量池的大小?

-128~127

Java的异常结构?

在Java中,所有的异常都有一个共同的祖先,那就是java.lang包中的Throwable类。Throwable类有两个重要的子类Exception和Error,Exception是程序本身可以处理的异常,可以被catch捕获,Exception又分为Checked Exception受检查异常和Unchecked Exception不受检查异常。Error是程序无法处理的错误,比如VirtualMachineError虚拟机运行错误、OutOfMemoryError内存溢出错误、NoClassDefFoundError类定义错误等等,这些错误发生时,JVM一般会选择终止线程。

Checked Exception和Unchecked Exception的区别?

Checked Exception是受检查异常,Java代码在编译过程中,如果受检查异常没被catch捕获或者没被throws关键字处理的话,就无法通过编译。除了RuntimeException及其子类以外,其他的Exception类及其子类都属于受检查异常 。常见的受检查异常有FileNotFoundException、ClassNotFoundException、SQLException等等。

Unchecked Exception是不受检查异常,Java 代码在编译过程中,我们即使不处理不受检查异常也可以正常通过编译。RuntimeException及其子类都是不受检查异常,常见的不受检查异常有NullPointerException、IllegalArgumentException、NumberFormatException、ArrayIndexOutOfBoundsException、ClassCastException等等。

ClassNotFoundException和NoClassDefFoundError的区别?

ClassNotFoundException是一个受检查异常,当程序试图通过完全限定的名称去加载一个类,但在类路径找不到它的定义时,就会抛出这个异常,通常发生在使用Class.forName()、ClassLoader.loadClass()这几个方法加载类的时候。

NoClassDefFoundError是一个错误,当Java虚拟机在编译时能找到这个类的定义,但在运行时找不到这个类的定义时,就会抛出这个错误,一般缺少依赖的jar包或定义的类丢失都会导致这个问题。

try-catch和throw和throws的区别?

try-catch用于捕获和处理异常,try里面放置可能抛出异常的代码,当异常发生时,程序会跳转到对应的catch中执行异常处理逻辑,catch可以处理特定类型的异常或者是它的父类异常。

throw用于手动抛出异常,在方法中使用throw关键字,可以主动将特定的异常抛给上层方法。

throws用于声明方法可能抛出的异常类型,添加在方法签名的尾部,它不会处理异常,也是将异常抛给上层方法。

详解try-catch-finally注意点?

try是必须的,catch和finally是可选的,但catch和finally必须存在一个或者都存在;

如果try或者catch中有return语句而finally没有return语句,那么try或者catch的return语句执行完后不会立即结束函数,而是将结果保存到栈帧的局部变量表中,然后再执行finally块中的代码。

如果finally中有return语句,那么会直接返回,不会执行try或者catch的return语句;

每个异常只能被catch一次。

泛型是什么?

泛型就是在定义类、接口、方法时不指定具体的参数类型,而是在使用它们时才指定具体的参数类型,会在编译期去检查参数类型是否正确,增强了代码的可读性和稳定性。

反射是什么?

反射指的是在程序运行时动态地获取和操作类、方法、属性等信息的能力,不需要在编译时确定这些信息,使我们的代码更加灵活。

缺点:反射的性能较低,因为需要在运行时动态查找和调用,所以性能不如直接调用。反射无法在编译期进行静态类型检查,只能在运行时发现错误,所以存在安全风险。

反射在框架中的应用?

Spring:

1. 依赖注入,Spring框架在应用启动时会扫描类路径下的所有组件,并使用反射来检测类中的注解信息,当发现类中标有@Autowired注解时会使用反射获取该属性的类型信息,并通过反射机制创建该类型的实例。

2、AOP,Spring框架在应用启动时会扫描类路径下的所有组件,并使用反射来检测类中的注解信息,当发现类带有@Aspect注解时会使用反射动态地创建该类的代理对象,然后代理对象会在目标方法的执行前后织入切面的通知。

反射获取Class?

调用实例对象的getClass方法:Class userClass1 = new USer().getClass();
类名.class:Class userClass2 = User.class;
调用Class.forName方法传入类路径:Class userClass3 = Class.forName("com.jun.entity.User");

API和SPI的区别?

一般模块之间都是通过接口进行通讯,服务调用者通过调用接口来获取服务提供者的提供的能力,它俩的主要区别就是接口的定义者不同。在API中,接口的规则是由服务提供者定义的。而在SPI中,接口的规则是由服务调用者定义的。

我举个简单的例子解释下,如果一家公司既负责设计芯片又负责制作芯片,那么这种情况就属于API。而如果一家公司只负责设计芯片,定义好这个芯片的标准,由其他公司按照标准制作并交付具有自家特色的芯片,那么这种情况就属于SPI。

静态代理和动态代理的区别?

在静态代理中,我们对目标对象中每个方法的增强都是手动完成的,需要对每个目标类都单独编写一个代理类。如果接口中新增加了方法,那么目标类和代理类都要进行修改,非常不灵活。

而动态代理是比较灵活的,不需要对每个目标类都创建一个代理类,甚至不需要目标类实现了接口,可以直接代理目标类。动态代理是在运行时动态生成类字节码并加载到JVM中的。

值传递和引用传递的区别?

对于值传递,方法接收的是实参值的拷贝,会创建副本,修改形参不会影响实参。

对于引用传递,方法接收的是实参所引用的对象在堆中的地址,不会创建副本,修改形参会影响实参。

Java是值传递还是引用传递?

在Java中只有值传递,如果参数是基本类型的话,传递的就是基本类型字面量值的拷贝,会创建副本。如果参数是引用类型的话,传递的就是实参所引用的对象在堆中地址值的拷贝,也会创建副本。

static和final的区别?

static用于定义静态成员变量、静态方法和静态代码块,静态成员变量和静态方法不依赖于类的实例,可以通过类名直接调用,静态成员变量在内存中只有一份,被所有实例共享,静态方法只能访问静态成员变量和静态方法,不能访问非静态的。静态代码块在类加载时就会执行里面的代码,常用来初始化静态资源。

再说final,被final修饰的类时不能被继承的,并且这个类中的所有成员方法都会被隐式地指定为final方法,被final修饰的方法是不能被重写的,被final修饰的变量是基本类型的话,值是不能被修改的,被final修饰的变量是引用类型的话,是不能再指向其它对象的。当希望某个类、方法或变量具有不可变性时,可以使用final修饰,安全性较高。

Java8的新特性主要有哪些?

第一个,可以使用default关键字在接口中定义具有默认实现的方法,使得我们向现有接口中添加新方法时,不会破坏已有的实现类。

第二个,提供了Lambda表达式,允许使用更简洁的代码去编写匿名函数,使编写过程更加方便。

// forEach遍历集合
list.forEach((item) -> System.out.println(item));
map.forEach((k, v) -> System.out.println(v));

// 排序,list排序用Collections,数组排序用Arrays
Collections.sort(list, (Integer o1, Integer o2) -> o1 - o2);
Arrays.sort(array, (Integer o1, Integer o2) -> o1 - o2);

// 新建线程
new Thread(() -> System.out.println("Hello World")).start();

// Lambda表达式在Stream API中也扮演着重要的角色,可以使用更简洁的代码处理集合数据
list.stream().filter(s -> s.startsWith("a")).collect(Collectors.toList());
list.stream().map(s-> s.length()).collect(Collectors.toList());

第三个,提供了用于处理集合数据的Stream API,可以通过流式操作的方式,对集合进行过滤、映射、排序、遍历、收集等一系列操作,常用的有filter、map、sorted、forEach、collect。

执行顺序:filter -> map -> sorted -> forEach/collect,forEach和collect方法是终止操作,它俩不能放在一起使用。

第四个,提供了一些新的用于操作日期和时间的类,比如LocalDate、LocalTime和LocalDateTime,位于java.time包中,使用起来比原来的Date类更加方便。

// 将字符串转为时间
LocalDate.parse("2024-5-12");
LocalTime.parse("12:12:22");
LocalDateTime.parse("2024-5-12 12:12:22");

// 日期计算
LocalDate.now().plusDays(1);
LocalTime.now().plusHours(1)(1);
LocalDateTime.now().plusDays(1);

// 获取本月的第一天
LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());

想起来的就这么多。

Java中一个对象占用的字节数?

对象在内存中的存储布局分为3块区域,分别是对象头、实例数据和对齐填充。对象头中包含8字节的MarkWord和4字节的KClassWord,一共占用12个字节,如果是数组对象的话,对象头中还会存储一个数组长度,此时对象头占用16个字节。

如果对象头和实例数据占用的字节数不是8的倍数的话,会进行对齐填充保证对象最终占用的字节数是8的倍数,比如我们创建一个没有任何属性的空对象,它的对象头占用12个字节,实例数据占用0个字节,然Java会给它填充4个字节保证最终字节数为16。

引用地址占4个字节。

URI和URL的区别?

URI是统一资源标志符,可以用来唯一地标识互联网上的任何资源,它包括URL和URN两个类别。

URL是统一资源定位符,它是一种具体的URI,不仅可以用来唯一地标识互联网上的任何资源,而且还提供了路由到这个资源的方式。

URN是统一资源名称,如果说某个人的家庭住址是URL的话,那么URN就相当于这个人的身份证号。

为什么浮点数运算的时候会有精度丢失的风险?

因为浮点数在计算机中是使用二进制表示的,而且在表示一个数字时宽度是有限的,如果小数对应的二进制是无限循环的,那么只能被截断,这时就会导致小数的精度丢失。

浮点数精度解决方案?

使用BigDecimal类不会造成精度丢失,它的底层使用了一个BigInteger对象存储数据,并且使用了一个int类型的变量指定小数点的位置。

Java为什么可以跨平台?

因为不同平台上都有相应的Java虚拟机实现,所以Java程序可以在任何支持Java虚拟机的平台上运行。

 

  • 61
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值