此文是自背整理的JAVA基础,若有问题,请多指教><有时间会持续更新的~
1.基础篇
1.1:基本的数据类型有哪些?
·整数类型:byte、short、int、long
·浮点类型 :float、double
·逻辑类型:boolean
·字符类型:char
1:2:char和vachar的区别?
char长度固定,vachar长度可变;char比varchar更方便存储和查找,varchar比char更节省空间
- 两者最大长度不一样:char最大长度是255字符,varchar最大长度是65535个字节
- char是定长的,不足的部分用隐藏空格填充,varchar是不定长的
- char会浪费空间,varchar会更加节省空间
- char查找效率会很高,varchar查找效率会更低
char查找效率比varchar更高是因为它具有固定长度的特性,可以直接根据偏移量进行定位,而不需要进行额外的长度计算。
CHAR
类型适用于那些长度不会改变或者长度变化很小的数据。例如,性别字段('M' 代表男性,'F' 代表女性),或者国家代码(如 'US'、'CN')等。
Varchar
类型适用于那些长度可能会变化的数据。如用户输入的文本、名称、地址等。如果字段的长度变化不大,或者对性能有较高要求,使用 Varchar
可能是一个好选择。
nvarchar(n)
包含 n 个字符的可变长度 Unicode 字符数据。n 的值必须介于 1 与 4,000 之间。字节的存储大小是所输入字符个数的两倍。所输入的数据字符长度可以为零。它表示存储的是Unicode数据类型的字符。我们知道字符中,英文字符只需要一个字节存储就足够了,但汉字众多,需要两个字节存储,英文与汉字同时存在时容易造成混乱,Unicode字符集就是为了解决字符集这种不兼容的问题而产生的,它所有的字符都用两个字节表示,即英文字符也是用两个字节表示。nchar、nvarchar的长度是在1到4000之间。和char、varchar比较起来,nchar、nvarchar则最多存储4000个字符,不论是英文还是汉字;而char、varchar最多能存储8000个英文,4000个汉字。可以看出使用nchar、nvarchar数据类型时不用担心输入的字符是英文还是汉字,较为方便,但在存储英文时数量上有些损失。
所以一般来说,如果含有中文字符,用nchar/nvarchar,如果纯英文和数字,用char/varchar
关于nchar/nvachar的原文链接:https://blog.csdn.net/lxd8731247769/article/details/47026517
1.3:a=a+b与a+=b的区别?
+=隐式的将操作的结果 类型强制转换为 持有的结果类型
byte a = 127;
byte b = 143;
a = a + b ;//error:cannot convert from int to byte!a+b操作会将a,b替身为int类型,将 int赋值给byte编译出错
a += b ;//ok +=将操作结果强制转换为 持有的结果类型,所以会成功输出
1.4: 3 * 0.1 == 0.3返回的是true还是false?
返回false,因为有些浮点数不能完全精确地表示出来
1.5:面向 对象的特征?
继承:子类继承父类的属性或者方法,避免重复编写代码
封装:把对象的属性或者方法封装起来,隐藏内部实现,只对外暴露接口
多态:同一类型对象对不同情况作出不同行为
1.6:定义一个无参构造方法的作用?
防止编译时报错(首先super()父类)
1.7:类中构造方法的作用?构造器Constructor能否被重写?
类中构造方法的作用是初始化对象;
构造器不能被重写但是可以被重载,(一个类中有多个构造方法)
1.8:重载和重写的区别?
重载:同样方法对输入的不同参数作出不同的处理
重写:发生子父类中,输入同样的参数,但是子类需要作出有别于父类或者覆盖父类的处理
1.9:==与equals()的区别?==与===的区别?
1、==一般是比较值,equals一般是内容的比较
2、== 只比较值,=== 比较类型和值
1.20:&与&&的区别?(|和||大差不差,但是是or的意思)
&是一个位运算符(按位与操作符),有0则0,也可以做逻辑与操作
&&是一个逻辑运算符(短路运算符),and 的意思
int a = 5;
int b = 3;
//按位与
int result1 = a & b;//即result1= 001; 101 & 011 = 001(二进制)
//逻辑运算
boolean result2 = (a == 5) && (b ==3);//result2 =true
1.21:重写equals()为什么要重写其hashcode?
只要equals相同,那么其hashcode一定相同;
如果只重写equals的话,新new 的对象的hashcode不同
1.22:为什么需要泛型?
1、适用于多种数据类型来执行相同的代码:比如相加操作,但参数类型多种
2、泛型中的类型在使用时指定,不需要强制转换
1.23:String、StringBuffer、StringBuilder的区别?
String:适用于少量的字符串操作。(常量,使用final修饰)
StringBuffer:适用于多线程下在字符串缓冲区进行大量操作。(变量,多线程 同步锁安全)
StringBuilder:适用于单线程下在字符串缓冲区进行大量操作。(变量,单线程)
1.24:接口和抽象类的区别?
- 接口一般是implements实现;抽象类的子类使用extends继承
- 接口中无main(),抽象类中有main()切可以运行它
- 接口中无构造函数,抽象类中有构造函数
- 接口方法默认使用public修饰,抽象类种方法可以使用任意修饰符
- 可以实现多个接口,但是只能继承一个抽象类
1.25:public、protected、default、private权限由高到低?
private > default > protected > public
- public:任何类都可访问,无论是否在同一个包中
- protected: 同一个包中的其他类或者不同包中的子类可访问
- default:只能被同一个包中的其它类访问
- private:只能被定义在同一个类中的其它成员访问
1.26:什么是反射?获取class对象的方法?
反射是指其它任意一个类可以知道该类的属性或者方法并且可以调用
获取class对象的方法:
1、调用耨个对象的getClass() 方法
Student stu = new Student();
Class stuClass = stu.getClass();
2、调用某个类的 class属性
Student stuClass = Student.class;
3、使用class类中的forName()
Class stuClass = class.forName("类的全路径");
1.27:创建java对象的方式?
1、使用new关键字
2、使用java反射的newInstance()方法
3、使用Object类的clone()方法
4、使用对象流ObjectInputStream()的readObject()读取序列化对象
1.28:break、return、continue区别?
break:是指跳出整个循环体,执行循环体下面的语句;
return:是指跳出所在的方法,结束该方法运行
continue:是指天厨当前这一次循环,继续执行下一次循环
1.29:final 、finalize() 、finally的区别?
final:是一个修饰符,可以修饰变量、方法、类,其修饰的变量在初始化后就不能被改变
finalize():是垃圾收集器将对象从内存中清理出去之前做必要得清理工作
finally:是一个关键字,与try-catch用于异常处理,finally一定会被执行
1.30:一个try可以跟随几个catch块?
可以跟随多个catch块,每个catch块用来捕获和处理特定类型的异常
//try-catch代码
try{
//代码块
}catch(IOException ioe){
//处理IO异常
}catch(SQLException sqle){
//处理SQL异常
}catch(Exception e){
//处理其它异常
}finally{
//无论发不发生异常,finally都会被执行
}
1.31:说说java中的异常?
Java中的异常(Exception)又称为例外,是一个在程序执行期间发生的事件,它中断正在执行程序的正常指令流。为了能够及时有效地处理程序中的运行错误,必须使用异常类。它们可以通过异常处理机制被捕获并处理。
下图举例了常出现的异常,(throws声明,try-catch块捕获处理)
1、编译时的异常:
文件不存在;网络错误...
2、错误:
内存溢出、线程死锁、虚拟机错误...
3、运行时的异常:
空指针;数组越界;类型转换异常;算术异常;参数不合法...
4、非运行时的异常:
IO异常;SQL异常...
1.32:java中异常处理机制?
异常处理机制用于在程序执行期间检测和处理和可能导致程序出错或意外的情况。例如,当程序尝试访问不存在的文件、网络连接中断或者输入错误的数据时,就会引发异常。
Java的异常处理机制由三个关键部分组成:捕获异常、抛出异常、处理异常
Java 中常见的异常处理机制:try-catch块,finally块,throws关键字(声明异常),try-with-resources语句(打开一个文件输入流并在代码结束时自动关闭它)
1.33:项目中什么时候抛出异常?什么时候捕获异常?
抛出异常(Throwing Exceptions):
①逻辑错误:例如,当一个方法接收到无效参数或违反了预期的使用条件时:
②外部系统故障:如数据库连接失败、网络超时、文件不存在等,应该抛出异常。
③资源耗尽:当资源(如内存、文件句柄)耗尽,且无法继续执行操作时,应该抛出异常
捕获异常(Catching Exceptions):
①预期的异常:对于那些你预期会发生并且能够处理的异常,应该在代码中捕获并进行适当的处理。
②异常处理:当你能够从异常状态中恢复,或者可以将异常转换为另一种形式的错误处理时,应该捕获异常
1.34:java集合?
1.35:ArrayList和LinkedList效率上的区别?
ArrayList基于动态数组,查询快;LinkedList基于双向链表,增删快
1.36:HashSet和ArrayList的区别
HashSet基于HashMap实现的,是一个不允许重复元素且元素是无序的
ArrayList基于动态数组,是一个允许重复元素且元素是有序的
1.37:说一说Map、HashMap、HashTable、HashSet?
①Map是一个接口,它定义了键值对的映射关系,HashMap和HashTable都实现了Map接口;
②HashMap是Map的一个子接口,它键值允许为Null,是非线程安全的,但是高效;
③HashTable也是Map的子接口,它键值不允许为null,是线程安全的,但是低效(因为Synchronized关键字对put等操作进行加锁,关键字它锁住的是整改hash表);
④HashSet是基于HashMap实现的,它是一个不允许重复元素且元素顺序是无序的;
不考虑线程安全且希望高性能用HashMap;考虑线程安全用HashTable;需要存储不重复元素用HashSet。
map的key可不可以为null?
答:不可以,因为 Map
需要能够准确地定位和存储值(value),而 null
作为键会导致无法区分存储的值。尝试将 null
作为键放入 Map
时,大多数 Map
实现(如 HashMap、
TreeMap
和 LinkedHashMap
)会抛出 NullPointerException
。但是Hashtable
是 Map
接口的一个古老实现,它允许一个 null
键和任意数量的 null
值。这是因为 Hashtable
在设计时没有考虑到 null
键会带来的混淆和潜在问题。
1.38:HashMap和LinkedHashMap的区别?什么是hash冲突?
HashMap存储元素不能保证其顺序,LinkedHashMap存储元素能保证有序。
hash冲突是指不同算法算出相同的索引值。
1.39:HashSet如何去重?
HashSet实质去重是通过HashMap实现的,每个元素在HashSet中都是HashMap的一个键(key),HashMap的键是唯一的,所以HashSet能自动去重。
⑴当元素被HashSet添加时,元素首先被传递给HashMap的hashCode()计算出哈希值
⑵再根据哈希码,HashMap会决定元素存储在哈希表的哪个桶(bucket)中
⑶若该桶中已经存在元素,则HashMap会调用该元素的equlas()方法检查是否与新加的元素相同,若相同,则不添加新元素,实现了去重
⑷若该桶中无元素或者equals()方法返回false,则添加新元素
1.40:HashMap的put()和get()实现原理?
HashMap的put(key,value)方法:
首先将k,v封装到Node(节点)对象当中,接着把key通过hashCode()方法得到哈希值,再通过哈希算法转换成数组下标 ,如果当前下标上下标位置上如果没有任何元素,就把Node添加到这个位置上;如果说下标对应的位置上有链表。此时,就会拿着key和链表上每个节点的key进行equals()。如果所有的equals()方法返回都是false,那么这个新的节点将被添加到链表的末尾。如其中有一个equals()返回了true,那么这个节点的value将会被覆盖。
HashMap的get(key)方法:
首先拿着key通过hashCode()方法得到哈希值,并通过哈希算法转换成数组下标。得到下标之后,在通过数组下标快速定位到某个位置上。如果这个位置上什么都没有,则返回null。如果这个位置上有单向链表,那么它就会拿着key和单向链表上的每一个节点的key进行equals,如果所有equals方法都返回false,则get方法返回null。如果其中一个节点的key和参数key进行equals返回true,那么此时该节点的value就是我们要找的value了,get方法最终返回这个要找的value
1.41:常用的读取文件方法?
①使用BufferedReader和FileReader读取(适用于较小的文件)
②使用Files类和Paths读取(适用于较大的文件且JAVA8以上)
③使用Scanner类读取(多种读取方法,可以用来解析不同类型的输入)
④使用InputStream和OutputStream读取(对于二进制文件:非文本文件(如图片、音频、视频等)
1.42:JDK,JRE,JVM区别
JDK(Java Development Kit)是整个 Java 的核心,是 java 开发工具包,包括
了 Java 运行环境 JRE、Java 工具和 Java 基础类库。
JRE(Java Runtime Environment)是运行 JAVA 程序所必须的环境的集合,包
含 java 虚拟机和 java 程序的一些核心类库。
JVM 是 Java Virtual Machine(Java 虚拟机)的缩写,是整个 java 实现跨平台
的最核心的部分,能够运行以 Java 语言写作的软件程序。
1.43:String常用的方法?字符串常用的拼接方法?
String常用的方法:
indexOf():返回指定字符的索引。
charAt():返回指定索引处的字符。
replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回一个分割后的字符串数组。
getBytes():返回字符串的 byte 类型数组。
length():返回字符串长度。
toLowerCase():将字符串转成小写字母。
toUpperCase():将字符串转成大写字符。
substring():截取字符串。
equals():字符串比较。
常用的拼接方法:
①使用 +
运算符
②使用 concat()
方法:这个方法不会改变原有的字符串,而是创建一个新的字符串。
③使用 StringBuilder或者
StringBuffer
类: StringBuilder
是一个可变字符序列,它提供了多种方法来修改字符串内容。StringBuilder
的 append()
方法可以用来拼接字符串,并且性能比用 +
运算符或 concat()
方法更优,特别是在循环中拼接大量字符串时。StringBuffer
是线程安全的,因此在多线程环境中使用时需要考虑性能开销。
1.44:如何把一个字符串变成一个字符集合?2例子
①使用Stream API: