1 . 面向对象和面向过程
面向过程 : 面向过程的性能较高,因为在面向对象,向java在运行时,类调用需要实例化,开销较大,消耗资源。所以当主要考虑性能时,向单片机,嵌入式开发等,主要采用面向过程开发。
面向对象 : 易维护,易扩展,易复用。以为面向对象有封装 ,继承 ,多态等特点,可以设计出有低耦合的系统,系统会更加灵活,易于维护。面向对象之所以比面向过程性能低,是因为,向java这种属于半编译语言,他需要先被jdk编译为 .class字节码,然后再由 jvm编译为二级制机器语言。
2 . java语言的特点
1)面向对象:继承,封装,多态
2)平台无关性:基于java虚拟机实现平台无关性
3)可靠性
4)安全性
5)支持多线程
6)编译与解释并存
3 . jvm
jvm是运行java字节码的虚拟机,jvm针对不同的系统的特定实现,只要给出相同的字节 码,jvm就可以运行出相同的结果
4 . 字符型常量和字符串常量区别
表面上:字符常量是单引号引起的一个字符;字符串常量是双引号引起
含义 :字符常量可以相当于一个整型值(ASCII值),可以参加表达式运算,而字符串常量相当于一个地址值(该字符串在内存中存放的位置)
占内存大小:字符常量(char)只占2个字节;字符串常量占若干个字节
字符型常量: 'a','b','c'..... 等 都是可以转化为整数型值,对应Asci值
字符串常量: String s="anbcsd"; 对应内容在内存地址中的地址。
5 . 构造器Constructor是否可以被override
Constructor不能被override(重写),但是可以被overload(重载),所以可以看到一个类中有多个构造函数的情况
重载和重写
1)重载 :重载就是同样一个方法能够根据输数据的不同,做出不同的处理
发生在一个类中,方法名必须相同,参数类型不同,个数不同,顺序不同,方法和返回值可以不同
2)重写 :有一个子类继承父类的方法,输入数据相同,但是运行结果必须不同,重写就是对父
类方法的重新改造,外部样子不能变,内部可以改变。
即遵循两同两小一大
两同 :方法名相同,形参列表相同
两小 :子类返回值类型应比父类方法返回值类型更小或者 相等,子类抛出的异常应比父类的方法抛出的异常更小或者相等
一大:子类方法的访问权限应比父类方法访问的权限更大或者相等
当父类方法访问修饰符为 final/private/static,子类则不能重写,但被static的方法能够被再次声明。
重写:在项目中对应 子类对于父类的继承,返回值类型,抛出异常大小子类都要小于父类。
比如ServiceImpl对于Service的继承,参数类型,以及返回值类型都要一致。
重载:在同一类中,相同的方法名,但是参数类型不一致,对数据处理结果也不一致
public class Father {
public static void main(String[] args) {
// TODO Auto-generated method stub
Father s = new Father();
s.sayHello();
s.sayHello("wintershii");
}
public void sayHello() {
System.out.println("Hello");
}
public void sayHello(String name) {
System.out.println("Hello" + " " + name);
}
}
————————————————
6. java面向对象三大特性:封装 继承 多态
1 .封装
封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果不想被外界访问,我们大可不必提供方法给外界访问。这样这个类也没啥意义了。
当我们创建一个属性的时候,我们需要对该属性进行封装,并提供一些对于外界访问的方法
我们对name,age等使用private进行私有化处理,同时提供一些get,set方法供外界使用。
下面就是对于属性name,xuehao,chengji,age的封装,但是我们需要提供对外界访问的方法
于是有了getAge,和setAge 方法。
public class students {
//名字
private String name;
//学号
private int xuehao;
//成绩
private int chengji;
//年龄
private int age;
public int getAge() {
return age;
}
public void setAge(int age) { //可以对setName添加一些细节,对主程序中输入的年龄有限制。
if(age<110&&age>0){
this.age = age;
System.out.println("输入恰当");
}
else System.out.println("您输入的结果不符合实际要求");
}
}
2.继承
使用已存在的类作为基础建立新的类,新类的定义可以增加新的数据,也可以用父类的功能。
1)子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问的,只是拥有
2)子类可以拥有自己属性和方法,即子类对父类进行扩展
3)子类可以用自己的方式实现父类的方法
我们可以通过子类继承父类的方法,同时对数据进行增强处理。
像ServiceImpl对于Service的继承
3 . 多态的两种实现形式 :
继承(多个子类对同一方法重写)和接口(实现接口并覆盖接口中的同一方法)
我们定义了一个公共接口buy,同时使用了三个类继承了这个接口
所谓多态就是指程序中定义的引⽤变量所指向的具体类型和通过该引⽤变量发出的⽅法调⽤在编
程时并不确定,⽽是在程序运⾏期间才确定,即⼀个引⽤变量到底会指向哪个类的实例对象,该
引⽤变量发出的⽅法调⽤到底是哪个类中实现的⽅法,必须在由程序运⾏期间才能决定
public interface Classic {
void Buy();
}
public class Fruit implements Classic {
public void Buy() {
// Fruit类的Buy方法实现
}
}
public class Clothing implements Classic {
public void Buy() {
// Clothing类的Buy方法实现
}
}
public class Food implements Classic {
public void Buy() {
// Food类的Buy方法实现
}
}
public class Shop {
public static void Buying(Classic classic) {
classic.Buy();
}
}
public class Sale {
public void mai() {
Classic one = new Fruit();
Classic two = new Clothing();
Classic three = new Food();
Scanner in = new Scanner(System.in);
int s = in.nextInt();
switch(s) {
case 1:
Shop.Buying(one);
break;
case 2:
Shop.Buying(two);
break;
case 3:
Shop.Buying(three);
break;
default:
System.out.println("你输入的商品类不存在,请重新输入");
}
}
}
public class Main {
public static void main(String[] args) {
Sale sale = new Sale();
sale.mai();
}
}
7 . String StringBuffer和StringBuilder
可变性
String底层由final关键字修饰,private final char value[] 所以不可变
StringBuffer和StringBuilde都是继承自AbstractStringBuilder,在AbstractStringBuilder 也是用字符串数组来保存字符串,但是没用final修饰,所以可变
线程安全性
String由final修饰,线程安全
StringBuffer对方法加了一些同步锁,线程安全
StringBuilder没加锁,线程不安全
性能
String类型每次改变,都会生成一个新的String对象。
StringBuffer每次都是对字符串本身进行操作
StringBuilder性能比StringBuffer高,但是却冒着多线程不安全的风险
总结:
操作少量数据:String
单线程操作字符流缓冲区:StringBuilder 多线程不安全,性能较高
多线程操作字符流缓冲区:StringBuffer
8. 自动拆箱与装箱
1 . 拆箱:将包装类型转为基本数据类型
2 . 装箱:将基本数据类型封装为包装类型
9 . 静态变量 接口 抽象类
1)在一个静态变量中调用一个非静态变量成员是违法的,因为在静态变量中不可以通过对象进行调用,因此在静态变量中,不能调用其他非静态变量,也不能调用其他非静态变量成员。
2)在java中定义一个不做事且没有参数的构造方法的作用
Java程序在执行子类的构造方法前,如果没有用super() 来调用父类的特定的构造方法,则会调用没有参数的构造方法,如果父类又没有调用特定的有参构造方法,则会造成编译错误。因为Java程序在父类中没有找到没有参数的构造方法。
3)接口和抽象类的区别
1. 接口默认用public,而所有的方法在接口中均不能实现,抽象方法则不一定。
2. 接口中除了有static,final变量,不能有其他变量,而抽象方法则不一定。
3. 一个类可以实现多个接口,但只能实现一个抽象类,接口本身可以通过extends继承多个接口。
4. 接口默认修饰方法public,而抽象方法可以被public,protected,defasult修饰。
5. 从设计层面来看,抽象是对类的一种抽象,是一种模板设计。而接口是对行为的抽象,
是一种行为规范。
接口对应于在项目中的Service接口,可以提供给外界继承访问
抽象类:是对某一种食物进行抽象处理,同时也需要提供一些共外界访问的方法
比如entity中的 person,User 都是对某一事物进行抽象化处理。
4)对象实例用什么创建的,对象实例和对象引用有什么不同
对象实例是用new创建
对象实例可以有多个对象引用指向它,而一个对象引用只能指向0个或者1个对象实例。
new一个对象Person(),这就是对象实例,同时提供一个person对象引用可以去引用它。
Person可以有多个对象引用去引用它,而一个对象引用只能引用一个对象实例。
Person person = new Person();
5)方法的返回值,他有什么作用
方法的返回值是执行方法代码的运行结果,它的作用是接受结果,使它用于下一步操作。
6)一个类的构造方法的作用是什么?如果一个类没有构造方法,那他能正常执行吗,为什么?
完成对类对象的初始化工作,可以执行,因为他可以执行不带参数的构造方法。
7)构造方法有哪些特性
1. 名字与类名相同
2. 没有返回值,不能用void声明构造函数
3. 生成类的对象时自动执行,无需调用
构造方法对应于实体类中,定义一个无参构造方法。
8)对象的相等和指向他们的引用相同分别代表什么意思
1. 对象的相同代表着它们内存中存放的内容相同
2. 引用相同代表指向他们的内存地址相同
9)在调用子类前会先调用他们的父类的没有参数的构造方法
帮助子类做初始化工作
10 . ==与equals(重要)
1 .== 判断两个对象的地址是否相同(基本数据类型==比较的是值相等 ,引用数据类型==比较的是引用内存地址是否相同)
2. equals 两种情况
1) 重写equals前,使用方法和==相同,一般比较的是引用对象内存地址是否相同
2) 重写equals后,比较的是对象内容是否相同。若内容相同,则返回true
11. hashCode与equals方法
1) hashCode介绍:hashCode作用是获取哈希码,哈希码也叫散列码,哈希码的作用是返回该对象在哈希表中的索引位置,散列码存储的是键值对,它可以根据键快速的查找到对应的值,这利用到了散列码。
2) hashCode的作用,当你把一个对象加入到HashSet(一个集合)中时,hashSet会先通过判断该对象的hashCode来判断该对象的位置,然后与其他hashCode作比较,如果没有相同的,hashSet会认为对象没有重复出现,如果有相同的hashCode值,这是会调用equals方法检查hashCode相等的对象是否真的相同,如果相同,则不会让其加入集合。如果不同,则会被hashSet散列到其他位置。
3)为什么重写equals方法一定要重写hashCode方法
1. 两个对象相同。则他们的hashCode相同,equals方法会返回true。但是他们的hashCode相同,他们的对象不一定相同,equals方法不一定会返回true。所以,equals方法被覆盖了,hashCode也必须被覆盖。
以上面的hashSet为例,hashCode的作用只是为了缩小查找范围。
12. 线程,进程和程序的概念
线程是更小单位的进程,一个进程可以有多个线程。一个类中的多个线程共享同一个内存空间和一组系统资源。所以系统创建一个线程或者线程切换,负担比进程小得多。所以,线程也被称为轻量级进程。
程序是含有指令和数据的文件,进程就是运行状态下的程序。
13. 线程有哪些基本状态
1. new 初始化状态
2. runnable 运行状态
3. blocked 阻塞状态
4. waiting 等待状态、
5. time_waiting 超时等待状态
6. terminated 终止状态
14. final 关键字的总结:变量,方法,类
1. 变量,被final关键字修饰的变量,如果是基本数据类型的变量,则其数值在初始化后便不能更改, 如果是引用数据类型,则该引用在创建之后不能指向其他对象。
2. 被final方法修饰的类,表明这个类不能在被其他类继承,同时,该类的中的所有方法都默认final 方法修饰,
使用final方法的原因是把方法锁定,以防任何继承类修改它的含义。
15. Java程序异常
Java中所有的异常都来与一个祖先throwable ,它包含两个,分别是exception和error。
1. exception包含的是程序本身可以处理的异常,通过catch捕获。同时也分为受检查异常和不受检查异常。受检查异常是必须要处理的(程序不能被正常编译),而不受检查异常是可以不处理的(程序能够正常编译)
2. error 不能够被程序处理的错误,只能避免。
throwable 常用方法
public string getMessage() :返回异常发⽣时的简要描述 public string toString() :返回异常发⽣时的详细信息 public string getLocalizedMessage() :返回异常对象的本地化信息。使⽤ Throwable 的⼦类覆 盖这个⽅法,可以⽣成本地化信息。如果⼦类没有覆盖该⽅法,则该⽅法返回的信息与 getMessage 返回的结果相同 public void printStackTrace() :在控制台上打印 Throwable 对象封装的异常信息
Java异常处理总结
try块:用于捕获异常,后面跟一个或者多个catch块,如果没有catch块,则必须跟一个 finally块
catch:处理捕获的异常
finally块:无论是否捕获异常,finall块中的语句都会被执行。当在try或者catch块中遇到return语句时,finall将在方法返回之前被执行。
a.在异常处理时,无论是否发生异常或try/catch中出现return语句,finally中的语句都会被执行
b.finally必须使用在所有catch的最后位置,常用来处理一些后续的工作,如释放资源
try{
代码
...
}catch(Exception e){
异常处理代码
...
}finally{
代码
...
}
以下三种情况finally不会被执行:
1. try或者catch块中用到了system.exit(init) 退出程序。
2. 程序所在的线程死亡
3. cpu关闭
16. Java序列化中,如果有一些字段不想进行序列化怎么办
对于不想进行序列化的字段,使用transient关键字修饰
transient关键字的作用:阻止实例中那些用此关键字修饰的变量序列化,当对象被反序列化时,被transient修饰的变量值不会被持久化和恢复。transient只能修饰变量,不能修饰类和方法
17. 通过键盘输入的常用的两种方法
1. Scanner
Scanner input = new Scanner(System.in);
String s = input.nextLine(); input.close();
2. BufferedReader
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s = input.readLine();
18. Java中的io流
按照流的方向划分为输入流和输出流
按照流的操作单元划分为字节流和字符流
按照流的角色分为节点流和处理流。
InputStream/Reader: 所有的输⼊流的基类,前者是字节输⼊流,后者是字符输⼊流。 OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
19. 有了字节流为什么还要有字符流
1. 无论是网络发送还是文件传输,信息的存储单元最小是字节,为什么还要分字节流和字符流操作。
字符流是由Java虚拟机将字节转换得来的,因为比较耗时,I/O流就提供了一个接口。
同时字符流对于传输字符比较方便。
———————————————————————————————————————————
Java集合总结
Java集合一共分为三个大类
List(对付顺序的好帮手):有序,可重复
Set(注重独一无二):无序,不可重复
hashMap(用key搜索的专家):采用key-value形式 。key不可重复,value可重复。一个key只能对应一个value
1. List集合中ArrayList和LinkList的区别
1)线程安全
ArrayList和LinkList都是线程不同步的,不保证线程安全
2)底层数据结构
ArrayList底层数据结构是Object数组,而LinkList底层数据结构是双向链表
3)插入和删除是否受位置影响:
ArrayList底层是Object数组存储,所以插入和删除受到位置影响,当没有指定位置,随即插入数值时,默认添加到ArrayList尾部,时间复杂度是O(1)。当有指定位置时,数值的时间复杂度是O(n-i)。因为在插入时,i 后面的数据要全部向后移动一位。
LinkList底层数据是双向链表,插入数据不受位置影响。当插入和删除数据没有指定位置时,默认添加到链表尾部。当指定插入数据位置为 i 时,时间复杂度是O(n),因为指针需要移动到指定位置才能插入和删除数据。
4)是否支持快速随机访问
LinkList不支持高效的快速随机访问,而ArrayList支持。快速随机访问指的是通过元素的序号快速查到元素的值。类似于(get(i))
5)内存空间占用
ArrayList会在尾部预留一些内存空间,而LinkList内存消耗最主要是每个元素都会比ArrayList多一个直接后继,直接前驱,和数据。
2. ArrayList和Vector的区别,为什么要用ArrayList替代Vector
ArrayList 是List的主要实现类,底层是Object[] 数组,适用于频繁查工作。线程不安全。
Vector 是List的古老实现类,底层是Object[] 数组,线程安全。
3. hashMap和hashTable的区别
1)线程是否安全
hashMap是线程不安全,hashTable是线程安全的,因为它的内部方法都经 synchronized修饰
2)效率
可能是因为线程不安全的原因,hashMap的效率比hashTable的高一点点。hashTable已经被淘汰,不要使用它。
3)Null key和Null value的支持
hashMap支持Null key和Null value。但是Null key只能有一个,Null value可以由很多个。
hashTable不支持Null key 和Null value
4)初始容量大小和每次扩充容量大小的区别
不指定初始值:
hashTable默认初始值为 11,后面每次扩容都会进行2n+1 式的扩容
hashMap 默认值是16 ,后面每次扩容原来的两倍。
指定初始值:
hashTable 会直接使用给定的大小
hashMap 会将其扩充大2的幂次方大小。
5)底层数据结构:
ArrayList(默认值是8)当链表长度小于阈值 64 时,链表为了减少搜索时间,会将链表转为红黑树。而未在到达阈值前,会进行数组扩充。hashTable则没有这样的机制。
4. hashMap与hashSet的区别
hashMap实现的是Map接口, hashSet实现的是Set接口
hashMap存储的是键值对, hashSet仅存储对象
hashMap调用put() 向map中存储对象, hashSet调用add() 向Set集合中存储对象。
hashMap使用键(Key)来比较hashCode hashSet使用成员对象来计算hasCode值。对于两个对象来说hashCode可能相同,所以用equals方法来比较。
5. hashMap的底层实现
jdk1.8之前:采用数组和链表结合在一起使用也就是链表散列
jdk1.8之后:采用数组扩容,当hashMap长度(默认为8)大于阈值(默认为64,将链表转换为红黑树之前会判断,如果未到达阈值,会进行数组扩容)时,会转换为红黑树,以减少搜索时间。
6. 比较HastSet,LinkHashSet,treeSet 的异同
HashSet底层是Set接口的主要实现类,底层是Object[] 数组,线程不安全。可以存储null 值
LinkHashSet 是HashSet的子类,可以按照添加的顺序遍历
treeSet 底层使用红黑树,能够按照元素的添加顺序遍历。排序的方式有自然排序和定制排序。
7. 底层框架数据结构总结
List
ArrayList :Object[] 数组
LinkList:双向链表
Vector:Object[] 数组
Set
HashSet:无序,唯一。基于hashMap实现,底层采用hashMap存储数据
LinkHashMap:是HashSet的子类,可以通过添加的顺序来遍历数据
TreeSet:有序,唯一。红黑树
Map
HashMap:java8之前,采用数组加链表组成,java8之后采用数组扩容到超过阈值则转为红黑树。
HashTable:数组加链表组成,数组是hashMap的主体,链表则是为了解决哈希冲突而存在的
TreeMap:红黑树。
如何选用集合
Map (根据键值获取元素值)
⽐如我们需要根据键值获取到元素值时就选⽤ Map 接⼝下的集 合,需要排序时选择 TreeMap ,不需要排序时就选择 HashMap ,需要保证线程安全就选⽤ ConcurrentHashMap
connection(只需要存储元素)
当我们只需要存放元素值时,就选择实现 Collection 接⼝的集合,需要保证元素唯⼀时选择实现 Set 接⼝的集合⽐如 TreeSet 或 HashSet ,不需要就选择实现 List 接⼝的⽐如 ArrayList 或 LinkedList ,然后再根据实现这些接⼝的集合的特点来选⽤。