Java基础简单一些问题
Java的数据类型
- 基本数据类型:byte,short,int,long,float,double,char,boolen
- 引用数据类型:数组,类,接口,枚举,注解,
变量的三要素和使用要求
- 数据类型、变量名,变量值
- 局部变量必须先声明再使用,变量必须初始化,成员变量有默认值;局部变量有作用域,同一个作用域中不能重复声明;给变量赋值时要求值的类型要<=变量声明的类型
基本数据类型变量和引用数据类型变量的区别
- 基本数据类型的变量:存储数据值,数据类型不同,宽度不同;
- 引用类型变量:存储地址值
Java的运算符“+”有几种意思
- 作为一元运算符,表示数值的正负
- 当左右两边有字符串出现的时候,表示拼接
- 其他情况表示求和
Java的自增和自减
- “++”、“--”在前表示变量自身先进行自增一或自减一运算后在参与计算
- “++”、“--”在后表示变量先参与计算后,自身再进行自增或自减运算
Java的运算符&和&&、|和||的区别
- &:逻辑与,按位与,不会发生短路情况
- &&:逻辑与,如果左边是false,就不会再看右边的表达式,也就是短路现象
- |:逻辑或,按位或;不会发生短路情况
- ||:逻辑或,如果左边是true,就不会再看右边的表达式,也就是短路现象
Java的运算符>>,<<,>>>的区别
-
:右移运算,右移几位表示除以2的n次方;不会发生正变负,负变正现象;
- <<:左移运算,左移几位表示乘以2的n次方;会发生正变负,负变正的现象
-
:无符号右移,正数的右移和>>一样,负数的右移,直接变正数;
Java的分支结构if...else和switch...case的区别;
- switch...case只适用于byte,short,int,char,String,枚举类型的常量判断;
- if...else适用于任何条件的判断;
- if...else不会发生分支穿透的现象,switch...else可能会发生分支穿透的现象
Java的循环语句
- for循环
- while循环
- do...while循环
Java的普通for循环和增强for循环的区别
- 普通for循环:任何需要重复执行代码的场景都适用;
- 增强for循环:只能用于遍历数组,或实现了java.lang.Iterable的集合;增强for循环遍历数组时,底层用的普通for循环;遍历集合时用的是集合的Iterable迭代器遍历。
关键字break,continue,return的区别
- break表示终止循环体方法;
- continue表示跳过本次循环,继续下次循环;
- return表示终止方法体的执行,并返回对应值(如果有返回值)
类和对象的关系
- 类是创建对象的模板
- 对象是类的实例
类的成员有哪些
- 成员变量
- 成员方法
- 构造器
- 代码块
- 成员内部类
静态成员变量、实例变量、局部变量的区别
- 静态成员变量:定义在类中,需要static修饰,有初始值,随着类的加载而加载;该类的所有对象共享该静态成员变量,可以加public,protected,private,transient,final等其他修饰
- 实例变量:定义在类中,有默认值,每个实例的变量的都是独立的,可以加public修饰
- 局部变量:定义在方法中,必须先声明再使用,只能加final修饰
构造器的特点
- 构造器的名字必须和类相同
- 构造器没有返回值
- 构造器的首行必须是this()或者this(参数列表)或者super()或者super(参数列表);如果没写默认是super()
- 构造器不会被继承,但是子类构造器一定会去调用父类的构造器;
- 如果没有定义构造器,系统将提供一个默认的无参构造
- 构造器只能加权限修饰符public,protected,缺省,private;枚举类和单例类的构造器一定是私有化的
- 构造器的调用必须用new关键字
方法的重载和重写的区别
- 方法的重载:在同一个类中出现方法名相同,参数列表不同的两个或多个方法叫做方法的重载(重载指载入的参数不同)
- 方法的重写:在子父类或接口中,出现方法方法名相同,参数列表相同的两个方法称为方法的重写(重写方法要求参数相同,返回值类型相同[基本数据类型],返回值类型是<=的[引用数据类型])、权限修饰符必须是重写的类可见的,且不能被static和final修饰;
可变参数
- 可变参数:参数类型出现...形式就称为可变参数;
- 在声明可变参数的方法中,可变参数就是数组
- 在方法参数列表声明中,可变参数要放在最后一位
- 在调用时,可变参数可以传递对应类型的数组,或者0~n个对应类型的元素
递归
- 方法出现自己调用自己的情况就叫做溢出
- 递归一定要有终止条件,避免出现栈溢出的情况
静态代码块和非静态代码块的区别
- 静态代码块:有static的修饰的代码块,是给静态变量初始化的。在类初始化的时候执行,一个类的静态代码块只会执行一次
- 非静态代码块:没有static修饰的代码块,是给实例变量初始化的。在实例初始化的时候执行,每次创建一个新的对象的时候都会执行一次;
静态方法和非静态方法的区别
- 静态方法:在本类中的任意成员都可以调用;父类的静态方法可以被子类调用,但不能重写。父接口的静态方法不会被实现类继承,也不能被重写;
- 非静态方法:只能在本类的非静态成员中被调用;非final修饰的非静态方法,只要子类、实现类可见,就可以选择重写;
抽象方法和非抽象方法的区别
- 抽象方法:没有方法体,由abstract修饰,不能由private,static,final,native修饰;在子类或实现类中需要重写,抽象方法只能出现在抽象类或接口中;
- 非抽象方法:没有abstract修饰,有方法体
关键字class、interface、enum的区别
- class声明类
- interface声明接口
- enum声明接口
继承的关键字
- extends
包的作用
- 组织管理不同的类
- 限制某些类的可见性范围
- 避免类的重名
实现接口的关键字
- implement
extends关键字的作用
- 表示子类继承父类,子接口继承父接口
- 泛型变量指定上限,<T extends Object&Comparable>
- 泛型通配符指定上限限,<? super Comparable >
package和import的区别
- package:声明包,必须在Java文件的首行
- import:导包, 在package和类定义语句之间
this和super的区别
- this代指当前对象
- super表示引用父类/父接口的成员
- this可以单独使用,但super必须在子类中使用
- this和super可以用于区分子类和父类中重名的成员方法或变量
如何理解面向对象的3个基本特征
- 封装:
- 为了体现高内聚、低耦合的开发原则
- 为了安全、隐藏类的内部实现细节、提高代码的复用性
- 继承:
- 为了提高代码的复用性,便于代码进行扩展
- 为了表示is-a的事务关系
- 多态:
- 为了代码编写更灵活,可以实现虚方法的动态绑定
如何理解多态性
- 一个类可以引用本类对象,也可以引用各种子类对象
- 一个对象可以让编译器按照本类处理,也可以按照父类或父接口类型,但是运行时类型不变
什么是基本数据类型的自动类型转换和强制类型转换
- 当把数据类型小的数据赋值给数据类型大的变量是,就会发生自动类型提升
- byte->short/char->int->long->float->double
- 当byte、short、char三个类型在计算时,就会自动升级为int
- 当数据类型小的数据与数据类型大的数据混合进行计算时,数据类型小的数据会自动类型提升
- 当把数据类型大的数据赋值给数据类型小的变量时,就要强制类型转换。
- double->float->long->int->short/char->byte
- 当希望某个数据类型小的数据按照某个大的数据类型计算时,也可以使用强制类型转换
什么是向上转型和向下转型
1.向上转型:
* 把子类对象赋值给父类的变量
* 把实现类的对象赋值给父接口的变量
2.向下转型:
* 把父类变量赋值给子类的变量
* 可能发生ClassCastException,向下转型之前加上instanceof判断
使用接口有什么好处
- 避免单继承
- 表示has-a的关系
枚举类的特点
- 枚举类的对象是固定的有限的几个常量对象
- 枚举类有固定的直接父类java.lang.Enum类,也不能有子类,构造器私有
包装类有什么作用
- 当必须使用对象时,基本数据类型就会自动装箱为包装类对象
- 当对包装类进行计算时,可以自动拆箱为基本数据类型
int,Integer,BigInteger
- int:基本数据类型
- Integer:包装类
- BigInteger:任意大小的整数
final、finally、finalize的区别
- final:修饰符
- final修饰类,表示类不能被继承
- final修饰方法,表示不能被重写
- final修饰变量,表示不能被修改值
- finally:
- 和try...cathc结构一起使用,表示无论是否有异常,是否有return语句,都会执行的finally块
- finalize
- finalize是Object类的一个方法,由GC调用,在对象被回收时调用,适用于释放JVM之外的内存
受检异常和非受检异常的区别
- 受检异常:也称之为编译异常,在编写代码时就会被编译器检测到,就会强制要求编写try...catch或throws进行处理;
- 非受检异常:也称之为运行异常,在编写代码的时候不会提示进行处理;
两种多线程的实现方式
- 继承Thread类或实现Runnable接口
String、StringBuffer、StringBuilder的区别
- String:字符串对象不可变,字符串常量可以共享
- StringBuffer和StringBuild:是可变字符序列。
- StringBuffer:线程安全
- StringBuilder:线程不安全
ArrayList和Vector的区别
- ArrayList:线程不安全的动态数组,数组初始化长度为0,默认扩容为1.5倍
- Vector:线程安全的动态数组,数组初始化长度为10,默认扩容2倍
ArrayList、Vector和LindkedList的区别
- ArrayList、vector:动态数组
- 需要扩容
- 非末尾位置增加、删除元素,需要移动元素
- ArrayList、Vector实现了List接口。
- LinkedList:双向链表
- 不需要扩容和移动元素。
- LinkedList实现了List、Queue、Deque接口。
Stack和LinkedList的区别
- Stack是Vector的子类,是顺序栈,底层是数组
- Linkedlist: 是链式栈,底层是双向链表
List和Set的区别
- List:
- 元素有序:元素的存储和添加顺序一致
- 元素可重复
- Set:
- 元素无序:元素的存储和添加顺序无关
- 元素不可重复
Collection和Map的区别
- Collection:存储一组对象
- Map:存储键值对
Hashtable和HashMap的区别
- Hashtable:线程安全的,不允许key和value为null
- HashMap: 线程不安全的,允许key和value为null
Hashtable、HashMap、TreeMap的底层实现
- Hashtable:数组+链表
- HashMap:JDK1,8之前:数组加链表,JDK1.8以后:数组+链表/红黑树
- TreeMap:红黑树
哈希表的底层数组长度为什么是2的n次方
- 因为2的n次方-1的二进制是前面都是0,后面几位都是1,这样的话,与hash进行&运算的结果能保证在[0,table.length-1]范围内,而且是均匀的。
- 如果手动指定一个非2的n次方的数组长度,HashMap是否接收呢?如果不接收怎么处理呢?
- 会纠正为>=手动指定长度的最近的一个2的n次方的值
哈希表的数组的元素类型
- java.util.Map$Entry接口类型
- JDK1.7的HashMap中有内部类Entry实现Entry接口
- JDK1.8的HashMap中有内部类Node和TreeNode类型实现Entry接口,并且TreeNode是Node的子类
哈希表的键值对如何计算存储位置
- hash&table.length-1
哈希表为什么要用链表和红黑树
- 为了解决hash和[index]冲突问题
- 两个不相同的key的hashCode值本身可能相同
- 两个不相同的key的hashCode值不同,但是经过hash()运算,结果相同
- 两个hashCode不相同的key,经过hash()运算,结果也不相同,但是通过hash&table.length-1运算得到的[index]可能相同
- 那么意味着table[index]下可能需要存储多个Entry的映射关系对象,所以需要链表或红黑树
HashMap的数组什么时候扩容
- JDK1.7版本:当要添加新Entry对象时发现size达到了threshold值,table[index]!=null时,两个条件满足会进行扩容
- JDK1.8版本:当要添加新Entry对象时发现size达到threshold值,table[index]下的节点达到8个,但是table.length又没有达到64.两种情况满足一种都会导致数组扩容
- 数组一旦扩容,都会导致所有映射关系重新映射调整存储位置
如何计算threshold值
- threshold=table.length*loadfactor
JDK1.8的HashMap什么时候树化,为什么要树化
- 当table[index]下的结点个数达到8个并且table.length已经达到64会进行树化
- 因为当table[index]下的结点个数超过8个后,查询效率就底下了,修改为红黑树的话,可以提高查询效率
JDK1.8的HashMap什么时候反树化,为什么要反树化
- 当table[index]下的节点个数少于等于6个
- 当继续珊瑚删除table[index]下的树节点,最后这个根节点的左右节点有null,或根节点的左节点为null,会反树化
- 当重新添加新的映射关系到map中,导致map重新扩容了,这个时候如果table[index]下面还是小于等于6的个数,那么会反树化
- 因为当table[index]下树的结点个数少于6个后,使用红黑树反而过于复杂了,此时使用链表反而更简洁高效;
已经存储到HashMap中的key的对象属性是否可以修改
- 如果该属性参与HashCode的计算,那么不能修改。因为一旦修改HashCode()就不是原来的值。而存储到HashMap中时,key的HashCode()-->hash()-->hash已经确定了,不会重新计算。用新堤hashCode值再查询get(Key)删除remove(key)时,算的hash值与原来不一致,就找不到原来的映射关系了
如果key是null,在哈希表中如何存储
- 会存在table[0]中
两个字符串比较用什么方法
- equals方法,如果要忽略大小写,用equalsIgnoreCase方法
TCP和UDP协议有什么区别
- TCP:面向连接的可靠的基于字节流的传输控制协议
- UDP:非面向连接的不可靠的基于用户数据包的协议
线程安全问题是什么,如何解决
- 当多个线程使用共享数据时,就会有线程安全问题。
- 可以加同步synchronized解决
- 同步代码块或方法
- 同步代码块:手动选择同步锁对象
- 同步方法: 静态方法的同步锁对象是当前类的Class对象,非静态方法的同步锁对象是this对象
IO流的四个抽象基类是什么
- InputStream:字节输入流
- OutputStream:字节输出流
- Reader:字符输入流
- Writer:字符输出流
如何实现对象的序列化
- 对象的序列化需要用ObjectOutputStream的writerObject方法,对象的反序列化需要用ObjectInputStream的readObject方法
- 对象需要实现java.io.Serializable接口,并加序列化版本ID
- 加transient和static修饰的成员变量都不会被序列化
Class类对象如何获取
- 类型名.class
- 对象.getClass
- Class.forName(类型全名称)
- 类加载器对象.loadClass(类型全名称)
反射的作用
- 实现Java语言的动态性
- 在运行时获取类信息,动态创建对象,动态操作属性,动态调用方法
什么是函数式接口
- 只有一个抽象方法的接口,即SAM接口(Single Abstract Interface)
什么是Lambda表达式
- Lambda表达式是一种实现函数式接口的新语法
举几个函数式接口的例子
- java.lang.Runnable
- java.util.Comparator
- java.util.function.Consumer
- java.util.function.Predicate
- java.util.function.Supplier
- java.util.function.Function
Comparable和Comparator的区别
- Comparable:自然比较接口
- Comparator:定制比较接口
Iterable和Iterator的区别
- Iterable:可迭代接口,实现它的集合就可以支持foreach循环遍历
- Iterator:迭代器接口
sleep()和wait()有什么区别
- sleep和wait都会导致当前线程进入阻塞状态,被挂起
- sleep不会释放锁,睡眠时间到会自动醒来,回到就绪状态
- wait是会释放锁,要通过notify()或notifyAll()唤醒,回到就绪状态
- sleep是在Thread类中声明的一个静态方法,Thread.sleep(毫秒)
- wait是在Object类中声明的非静态方法,必须锁对象调用
请解释Java异常处理机制相关的5个关键字
- try:尝试执行可能发生异常的代码
- catch:尝试捕获try部分发生的异常,可以存在多个catch,如果多个catch的异常类型有继承关系,那么遵循子上父下
- finally:无论是否发生异常,都会执行的代码块
- throws:在方法声明中指出可能抛出的异常
- throw:手动抛出异常,可以抛出系统异常,也可以抛出用户自定义异常,而用户自定义异常必须用throw语句抛出,可以代替return语句结束方法运行
访问修饰符的作用范围由大到小,及各自的范围是什么,可以修饰什么
- 修饰符的范围由大到小:public,protected、缺省、private
- public:所有人都可以访问
- protected:本类和本包,其他包的子类可以访问
- 缺省:本类和本包可以访问
- private:仅本类可以访问
- 可以修饰的角色
- public:可以修饰类、成员变量、成员方法、成员内部类
- 缺省:可以修饰类、成员变量、成员方法、成员内部类
- protected:可以修饰成员变量、成员方法、成员内部类
- private:可以修饰成员变量、成员方法、成员内部类
列出一些常用的类、接口、包,各至少5个
- 常用类:String、Math、ArrayList、HashMap、System、Scanner、LinkedHashSet
- 常用接口:Serializable,Collection,Map,Set,List
- 常用包:java.lang,java.util,java.io,java.math,java.net,java.text
学习要有计划、代码要经常练习、学习之后要有输出、多交流、多总结、找出规律。
忌三天打鱼两天晒网、浅尝辄止、闭门造车