(一)金三银四面试抢攻-Java基础-知识复盘-面试集锦

金三银四面试抢攻-Java基础-知识复盘-面试集锦
1.Java概念


1.1.Java特点与特性


1.1.1.特点


跨平台,面向对象,安全性,多线程,简单易用,既是编译型又是解释型


1.1.2.特性


1.1.2.1.封装


隐藏对象的属性和实现细节,仅仅对外公开接口。
封装具有一下优点:
a.便于使用者正确、方便的使用系统,防止使用者错误修改系统属性;
b.有助于建立各个系统之间的松耦合关系;
c.提高软件的可重用性;
d.降低了大型系统的风险,即便整个系统不成功,个别独立的子系统有可能还有价值。
封装的两大原则:
a.把尽可能多的东西藏起来,对外提供简洁的接口;
b.把所有的属性封装起来。


1.1.2.2.继承


子类和父类之间的继承关系,子类可以获取到父类的属性和方法。


1.1.2.3.多态


java语言允许某个类型的引用变量引用子类的实例,而且可以对这个引用变量进行类型转换。


1.1.2.4.抽象


现实生活中的事物被抽象成对象,把具有相同属性和行为的对象被抽象成类,再从具有相同属性和行为的类中抽象出父类。


1.2.JVM、JDK、JRE到底有什么区别

 

1.3.字节码是什么以及它的优点?


字节码就是Java源代码经过编译后生成的.class文件,面向虚拟机,由虚拟机解释执行
优点:
a.面向虚拟机,一次编译,多次运行
b.在一定程度上解决了传统解释性语言执行效率低的问题,又保留了解释性语言的可移植性


1.4.什么是编译型?什么是解释性?Java属于什么类型


编译型:使用特定的编译器,针对特定的平台,将高级语言的源代码一次性编译成可被平台硬件执行的机器码。
解释型:使用特定的解释器,将高级语言的源代码逐行解释成特定平台的机器码并立即执行。
Java既是编译型又是解释型。Java源文件由Java编译器编译成.class文件,由JVM解释执行。

 

1.5.什么是JIT


JIT(just in time)运行时编译,将高频调用的方法或代码块编译成本机机器代码。(对解释执行的一种优化)


1.6.面向对象与面向过程


面向过程就是分析出解决问题所需要的步骤,用函数将所有的步骤一步一步实现,然后再依次调用执行。

 

面向对象就是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事务在整个解决问题的步骤中的行为。

 

2.语法


2.1.i++与++i的区别(同理i--与--i)


符号在前,先自增(或自减)再赋值。
符号在后,先赋值再自增(或自减)。
注意:char类型也可以++或--操作

 


2.2.continue、break、return的区别


continue 跳出本次循环,继续执行下一次循环
break 结束整个循环,继续执行循环以外的方法
return 直接结束整个方法。


2.3.Java native 方法


一个native方法是指该方法的实现由非Java语言实现,比如C或C++。用native声明,告知JVM该方法的定义在外部。


2.4.==与equals的区别与关联


基本数据类型:==判断的是基本数据类型的值是否相等
引用数据类型:==判断是对象的内存地址是否相等
equals用于判断俩个对象是否相等。
Object中的equals()方法 如下

 

所有的类都继承于Object,所以在不重写equals()的情况下,equals()判断的同样是对象的内存地址是否相等。


2.5.hashCode与equals的分析


常见面试题:为什么equals()方法重写后,hashCode()也尽量要重写?
因为hashCode常规协定:如果根据equals()方法,俩个对象是相等的,那么hashCode也必须相等,所以只重写equals()方法,有可能会导致俩个对象equals() 相等,而hashCode 不相等。所以在重写equals()与hashCode()方法时,所取的变量因素要相同。例如Object中equals()方法,比较的时俩个对象的内存地址,hashCode()方法,是通过对象的内存地址计算hash值。
详解如下:


2.5.1.hash、hash函数与hash表


hash: 散列,把任意长度的输入,通过散列算法,变换成固定长度的输出,即为散列值。这种转化实为一种压缩转换,散列值的空间远小于输入值的空间。
hash函数:即为hash算法的具体实现,通过hash函数获得hashCode值
常见hash函数如下:
a.直接寻址法。取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a·key + b,其中a和b为常数(这种散列函数叫做自身函数)
b.数字分析法。分析一组数据,比如一组员工的出生年月日,这时我们发现出生年月日的前几位数字大体相同,这样的话,出现冲突的几率就会很大,但是我们发现年月日的后几位表示月份和具体日期的数字差别很大,如果用后面的数字来构成散列地址,则冲突的几率会明显降低。因此数字分析法就是找出数字的规律,尽可能利用这些数据来构造冲突几率较低的散列地址。
c.平方取中法。取关键字平方后的中间几位作为散列地址。
d.折叠法。将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和(去除进位)作为散列地址。
e.随机数法。选择一随机函数,取关键字作为随机函数的种子生成随机值作为散列地址,通常用于关键字长度不同的场合。
f.除留余数法。取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址。即 H(key) = key MOD p,p<=m。不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。对p的选择很重要,一般取素数或m,若p选的不好,容易产生碰撞。
hash表:通过hash函数得到hash值就存放于hash表中。


2.5.2.hashCode


hashCode就是通过hash函数计算得来,每个对象都有hashCode。对象默认的hashCode的计算都是来自于Object对象中的native方法hashCode()

 

该方法通过对象的内存地址(物理地址),由hash函数计算得到hashCode。由此我们可以看到,Object equals()比较的是俩个对象的内存地址,Object hashCode()方法是通过对象内存地址计算hashCode ,因此可以保证,equals()相等的情况下,hashCode一定相等。


2.5.3.hashCode的作用


hashCode的作用主要是为了查找的快捷性。
例如现在有一块可以存放100个数的内存,需要存储100个不一样的数据,正常情况下,每存储一个数,都需要与内存中已有的每一个数进行比较,很显然,这样很麻烦。那么采用hashCode的形式会方便很多。

 

如图所示:当存储65时,通过hash函数计算出hashCode值为2,那么只需要将65与内存中已有的数据且hashCode同为2的数值进行比较。无须同每一个数据进行比较。


2.5.4.hashCode与equals的关系


a.如果equals相等,那么俩个对象一定相等。hashCode也一定相等。
b.如果俩个对象的hashCode相等,那么只能说明俩个对象在散列存储结构中,存放于同一位置,但对象并不一定相等。也就是equals不一定相等。


2.6.包装类的自动装箱与自动拆箱


包装类的作用:
集合不允许存放基本数据类型,只能存放应用数据类型。
基本类型可以和包装类型直接相互转换,自动装箱拆箱。
通过包装类型的parse方法可以实现基本数据类型+String类型之间的相互转换。
函数需要传递进去的参数为Object类型,传入基本数据类型就不可行。
什么是自动装箱与自动拆箱?

 

Integer i = 10; 即为自动装箱,装箱过程其实会转化为Integer i = Integer.valueOf(10);
int j = i ; 即为自动拆箱,拆箱过程会转化为int j = i.intValue();


2.7.包装类的常量池


Integer、Short、Byte、Character、Long 都具有常量池
Double、Float并未设置常量池
Boolean只有两个值true和false
Integer
Integer内部静态类有一个数组缓存。static final Integer cache[];看内部实现我们可以知道,默认下该数组缓存存放数据范围为[-128,127]

 

再看Integer的valueOf()方法

 

判断如果参数i在数组cache[]范围内,则在缓存中直接提取对应的包装类对象,如果不在该范围内,则重新创建。
Byte
同理,Byte


Short

 

 


Long


Character
Character缓存池中存储的范围是[0,127],对应的ASCII表

 


ASCII表

 

Double
Double,Float并没有常量池,valueOf()的每次调用都会新建对象

 

Float

 

2.8.重写与重载


重写:
a.发生在父类与子类之间
b.方法名,参数列表,返回类型(除过子类中方法的返回类型是父类中返回类型的子类)必须相同
c.访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)
d.重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常
重载:
a.重载Overload是一个类中多态性的一种表现
b.重载要求同名方法的参数列表不同(参数类型,参数个数甚至是参数顺序)
c.重载的时候,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准


2.9.泛型


2.9.1.什么是泛型?


泛型的本质就是将类型参数化,将类型的定义为变量


2.9.2.泛型的好处


泛型的好处就是在编译时期就可以进行类型安全检查,并且所有的强制转换都是自动和隐式的。


2.9.3.泛型中T、E、K、V、?的区别


本质上这些个都是通配符,没啥区别,只不过是编码时的一种约定俗成的东西。我们可以换成 A-Z 之间的任何一个 字母都可以,并不会影响程序的正常运行,但是如果换成其他的字母代替 T ,在可读性上可能会弱一些。通常情况下,T,E,K,V,?是这样约定的:
?表示不确定的 java 类型,可以是任何一种类型
T (type) 表示具体的一个java类型
K V (key value) 分别代表java键值中的Key Value
E (element) 代表Element


2.9.4.泛型的上下边界


上界通配符:<? extends E>,用 extends 关键字声明,表示参数化的类型可能是所指定的类型,或者是此类型的子类。
下界通配符:<? super E>,用 super 进行声明,表示参数化的类型可能是所指定的类型,或者是此类型的父类型,直至 Object。


2.10.注解


2.10.1.注解是什么?


注解就是对接口、类、变量、方法进行标记,来告诉编译器或APT该如何操作。(APT:提取、处理注解的相关代码操作),注解对于代码本身的运行并没有直接的影响。
例如:@Test注解,就是告诉junit框架,需要将@Test标记的方法进行单元测试。


2.10.2.注解的作用


a.提供信息给编译器: 编译器可以利用注解来探测错误和警告信息
b.编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、Html文档或者做其它相应处理。
c.运行时的处理: 某些注解可以在程序运行的时候接受代码的提取


2.10.3.注解的定义


通过@interface来声明

 

2.10.4.元注解


在定义注解时使用的注解,也就是对自定义注解的标记。例如


a.@Retention
定义注解的生命周期
参数定义:
RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。
RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。
b.@Documented
能够将注解中的元素包含到 Javadoc 中去。
c.@Target
定义注解的运用场景
ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
ElementType.CONSTRUCTOR 可以给构造方法进行注解
ElementType.FIELD 可以给属性进行注解
ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
ElementType.METHOD 可以给方法进行注解
ElementType.PACKAGE 可以给一个包进行注解
ElementType.PARAMETER 可以给一个方法内的参数进行注解
ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
d.@Inherited
继承。被@Inherited标记过的注解,具有继承效果
例如:

 

 

注解@MyAnnotation 被@Inherited标记,所以当classA 被注解@MyAnnotation标记,classB继承classA时,classB默认也拥有@MyAnnotation注解。
e.@Repeatable
可重复注解。


2.10.5.注解的成员变量


注解只有成员变量,没有方法。注解的成员变量在注解的定义中以“无形参的方法”形式来声明。可由defaul指定默认值。

如果一个注解内仅仅只有一个名字为 value 的属性时,应用这个注解时可以直接接属性值填写到括号内。


2.10.6.JDK内置的注解


Overried
Overried是告诉编译器要检查该方法是实现父类的方法。
Deprecated
Deprecated用于标记一些过时的代码。
SuppressWarnings
SuppressWarnings用于消除一些警告信息,使用集合的时候,如果没有指定泛型,IDE会提示安全检查的警告。
FunctionalInterface
FunctionalInterface是JDK8中的注解,用来指定该接口是函数式接口。
SafeVarargs
SafeVarargs是JDK 7中的注解,主要目的是处理可变长参数中的泛型,此注解告诉编译器:在可变长参数中的泛型是类型安全的。


2.10.7.注解的提取


注解通过反射提取。
Class对象的isAnnotationPresent() 方法判断它是否应用了某个注解

getAnnotation() 方法来获取指定 Annotation 对象。

getAnnotations() 方法获取所有的注解对象。

 

2.10.8.注解的使用场景


a.生成文档:Swagger中就是通过注解对接口,实体类中的字段进行描述生成可视化的文档
b.代替配置文件:Spring中Bean的装载注入
c.导出数据:可以写一个统一的导出工具类,传入一个List<实体类>进去即可导出Excel文件,Excel的表头可以用注解加载字段上
d.框架层面的统一处理:注解在底层框架中用的比较多,在框架中需要考虑到通用性,能用注解做很多事情,比如对API进行权限控制,限流等操作都可以通过自定义注解来标识是否需要进行认证,限流等,还有数据的缓存,典型的就是@Cacheable,还有异步方法的调用@Async,ORM框架中的使用,可以用注解标识表名,字段名,JPA中,Spring Data框架中都有使用。

更多系列文章,可以关注公众号“程序员之面霸突击队”。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值