JAVA 基础
一. Java八种基本数据类型和所占的字节
Java 采用unicode编码,每个字节占8位
1. byte 1
2. short 2
3. int 4
4. long 8
5. float 4
6. double 8
7. char 2
二. JVM/JDK/JRE
1. JVM java虚拟机
它是一次编译随处运行的关键所在
.class到机器码这一步会通过解释器执行,速度会慢。然后java使用lazy evaluation,执行次数越多的代码速度会越快。所以java是编译和解释共存的语言
2. JDK ,JRE
Jre是java运行时的环境,只能运行程序,不能创建新程序
Jdk时功能齐全的java sdk ,有jre的一切,还有编译器javac和工具,可以创建/编译程序。
3. Java 解释和编译共存
就像是要看英文书,可以等翻译人员全部翻译完再读(编译)翻译的人翻译一段你就阅读一段(解释)
编译就是编译器针对特定的os,把源代码一次性翻译成可被平台执行的机器码
解释就是杰时期对程序逐行解释然后立即执行
4. OpenJDK/Oracle JDK
Open 完全开源,oracle 不完全开源
Oracle 相对更稳定
在响应性和jvm性能方面oracle更好
三. Java和c++的区别
相同点:都是面向对象
不同点:
Java不提供指针直接访问内存的功能,程序内存更安全
Java的类单继承;C++多继承;Java 接口可以多继承
四. 基本语法
1. 字符型常量和字符串常量
字符常量是单引号引起的一个字符,字符串常量是双引号引起的0/若干个字符
字符常量可以参加表达式运算,相当于整型(ASCII值);字符串常量:地址
字符:2byte;字符串:若干
2. 标识符和关键字
标识符:名字
关键字:特殊的标识符
3. 自增自减
B=++a a先自增再赋值给b
B=a++ a先赋值给b再自增
4. 范型:本质是参数化类型,所操作的数据类型被指定为一个参数
使用方式:
(1)范型类
(2) 范型接口
(3)范型方法:可以写一个范型方法,在调用的时候可以接受不同类型的参数,根据传递给范型的参数类型,编译器会适当处理没用过方法调用
·· 通配符:T/E/K/V/?
? 不确定的java类型
T(type)具体的一个java类型
KV是key value
E element
5. 构造器的作用
构造器负责成员变量的初始化,创建一个对象的时候系统会进行默认初始化,如果想改变,就通过构造器来实现(初始化成员属性)
构造器可以有任何访问修饰符,可以没有返回值也不需要void
构造器一般首字母大写,方法一般驼峰式
构造方法的名字必须和所在类的一致
方法中的this指向执行方法中类的实例,
6. ==和equals
对于基本数据类型来说,==比较的是值;对于引用数据类型,比较的是内存地址
但因为java只有值传递,所以对于==来说,不管是比较基本数据类型还是引用数据类型的变量,本质都是比较值只是引用类型变量存储的值是对象的地址
Equals()不能判断基本数据类型的变量,只能判断两个对象是否相等。
所以再类当中通过equals()比较两个对象是等价于通过==比较两个对象的,只不过使用的默认是Object里面的equals方法。
6.1 String里面的equals方法是被重写过的,因为String里面的equals比较的是对象的值。创建string类型的时候jvm会在常量池中查找有没有和要创建对象相同的值。
7. Int 和Integer
Integer必须是实例化才能使用
Integer是对象的引用,所以new一个Integer实际上是生成一个指针指向这个对象,而int则是直接存储数据。
Integer和Integer比较,因为指针指向两个地方,所以false
Integer和int比较会进行自动装拆箱,所以true
Int 和int 就是true,因为是直接存储数据
8. 原始数据类型和引用数据类型
虽然java号称一切都是对象,但原始数据类型是例外
9. hashcode和equals
(1) 在java中作用是一样的,用来比较两个对象是否相等
(2) Equals已经实现对比的功能了,但equals比较全面,复杂,因而效率低;但hashCode()效率高
(3) 但是hashCode()不一定完全可靠,因为hash碰撞。
Equals()相等的两个对象hashCode()一定相等;hashCode()相等的两个对象equals()不一定相等。
(4) 所以为了应对需要大量快速对比的时候,先用hashCode()去比,不一样则两个对象肯定不相等,如果一样再用equals去比。
9.1 为什么重写equals()时必须重写hashCode()
如上所示,hashCode()必须完成的事情是:为equals认定为相同的对象返回相同的hash值。
举个例子:String的equals()方法是被重写了的,重写后如果每个字符串都相等,即使两个string地址不一样,它们equals()也为true;
这是如果没有重写hashCode()方法,那String会调用自己父类Object里面的hashCode方法,那因为两个地址值不一样,所以会生成两个不一样的hash值。这就违反了上面所说的hashCode()需要为equals认定为相同的对象返回相同的hash值。
9.2 Equals()和hashCode()使用注意事项
首先为什么要重写hashcode():因为hashCode()是object里的方法,返回的只是当前对象的地址,那再一个类里面new两个对象地址肯定不同,hashcode()也不同了,所以这时候要重写hashCode()方法。
五. 基本数据类型
1. Java基本数据类型以及对应的包装类型,各占几个字节
(1) 6种数字类型:byte,short,int,long,float,double
(2) 字符类型 char
(3) 布尔类型 Boolean
Char用的是单引号,在算法里面有看到过,需要了解。
(4) 原始数据类型包括 int long boolean double byte char float short
(5) 对应的包装类型 Integer Long Boolean Double Byte Char Float Short
基本数据类型默认值不是null,一般有默认值,包装类型不赋值就是null;
(6) 从JVM的角度来说,基本数据类型都放在Jvm栈种的局部变量表;包装类型属于对象类型,对象实例都存储在堆中。(和对象类型相比,基本数据类型占用空间很小)
2. 自动装拆箱
装箱:将基本类型用对应的引用类型包装起来。调用了valueOf()
拆箱:将包装类型转化为基本数据类型,调用了xxValue()如intValue();
3. 包装类和常量池
(1) Byte,Short,Integer,Long默认创建[-128,127]的相应类型缓存数据,Character创建[0,127]范围的缓存。
(2) Float ,Double没有实现常量池技术
(3) 所有Integer之间的比较都要用equals,如果是-128,127内的区间,已经在字符串常量池了,就可以直接用==,剩下的都在堆上产生,不会复用已有的对象。
六. 方法(函数)
1. 方法的返回值
获取某个方法中代码执行后产生的结果。返回值的作用就是接收结果。
2. 方法的类型:就是参数和返回值的有无排列组合;有参数有返回值,有参数无返回值blabla
3. 为什么在静态方法中调用一个非静态成员是非法的
从JVM的角度说,静态方法是属于类的,在类加载的时候会分配内存,可以通过类名直接访问。但非静态成员属于实例对象,只有在对象实例化后才存在,然后通过类的实例对象去访问。
因此,在类的非静态成员不存在的时候静态成员已经存在了,此时如果调用内存中还不存在的非静态成员,是非法的。
4. 静态方法和实例方法的不同
(1) 外部调用静态方法,使用的是类名.方法名的方式;也可以是对象名.方法名的模式。实例方法只有后面这种模式,所以调用静态方法可以无需创建对象。
(2) 静态方法在访问本类的成员时,只允许访问静态成员而不允许访问实例成员变量和实例方法。实例方法则没有这个限制。
5. 为什么Java中只有值传递
https://segmentfault.com/a/1190000021529503
按值调用:调用函数时将实际参数复制一份传递给函数
按引用调用:调用函数的时候将实际参数的地址传递给函数,这样函数中对参数的修改将影响到实际参数
Java 程序总是按值调用,方法得到的是所有参数值的一个拷贝,方法不能修改传递给它的任何参数变量的内容。
6. Java方法参数使用情况:
一个方法不可以修改基本数据类型的参数;
一个方法可以改变对象参数的状态
一个方法不能让对象参数引用一个新的对象
7. 重载和重写的区别
(1) 重载:根据输入数据的不同做不同的处理
方法名相同,参数不同
(2) 重写:子类继承父类相同的方法,输入一样的数据但给出不同的返回值。
方法名参数都一样
(外壳不变,核心重写)
重写时返回值类型,方法名,参数列表必须相同。
构造方法无需被重写
8. 深拷贝和浅拷贝
浅拷贝:对基本数据类型进行值传递;引用数据类型进行引用拷贝
深拷贝:基本数据类型值传递,引用数据类型创建新对象,复制内容。
七. java面向过程和面向对象
1. 面向过程和面向对象的区别
面向过程性能高于面向对象。因为类调用需要实例化,开销比较大。
但面向对象易维护易拓展,具有封装继承多态等特性,使系统更容易维护
但java性能差不是因为面向对象,而是因为它是半编译语言,最终执行的代码ing不是可以直接被cpu执行的二进制机械码。
2. 成员变量和局部成员变量
(1) 成言变量属于类,举不避纳凉则是代码块/方法中定义的变量or方法参数。成员变量可以被public/private/,举不避纳凉不可以。但局部变量和成员变量都可以被final修饰
(2) 成员变量用static修饰则属于类则成员变量属于类;否则属于实例
(3) 成员变量是对象的一部分,随着对象创建存在;局部变量随着方法调用而消失;
(4) 成员变量如果没有被赋予初值,则会自动以类型的默认值复制;局部变量不会。
3. 创建对象用new运算符;对象实体指的是对象的实例;一个对象引用可以指向0/1个对象;一个对象也可以有n个引用指向它。
4. 对象相等指的是内存中存放的内容相等;引用相等指的是指向的内存地址是否相等。
5. 类构造方法的作用是完成类对象的初始化工作。就算累没有生命构造方法,页可以执行,因为类即使没有生命构造方法也会有默认不带参数的构造方法。
其实我们在不知不觉的使用构造方法,创建对象的后面要加括号也是因为要调用无参的构造方法。
如果重载了有参的构造方法,无参的构造方法也要写出来。(why)
6. 构造方法的特点
名字与类相同;没有返回值,但也不能用void声明构造函数;生成类的对象时自动执行,无需调用;
构造方法不可以被重写但可以被重载;所以一个类可能有多个构造函数。
八. 面向对象的三大特征
1. 封装
将对象属性隐藏在内部,不允许外部对象直接访问内部信息,但可以提供一些被外界访问的方法。
例如我们看不到空调的内部,但我们可以通过遥控器来访问空调;
2. 继承
不同类型的对象也会有相同点和不同点;
继承使用已经存在的类作为基础,来建立新的类,新定义的类可以有新的数据和功能,也可以使用父类的功能。
但是子类不可以访问父类中的私有属性和方法,只能是拥有。
继承可以快速创建新的类,提高代码的重用;节约时间,提高效率。
3. 多态
一个对象具有多种状态,具体表现为父类的引用指向子类的实例;
九. String/StringBuffer/StringBuilder 区别是什么?String为什么不可变?(一看就是面试题)
1. 可变性:String使用final关键字修饰字符数组并保存字符串,所以string是不可变的(java9之后使用byte数组存储),由于它不可变,所以拼接,裁剪都需要new新的对象,影响性能;
不可变的主要作用是当一个对象需要被多线程共享而且访问频繁的时候,可以节约时间,提高性能(因为不需要同步也不需要等待锁)
2. StringBuffer就是用来解决String性能而提供的一个类,它是线程安全的,但也有额外的性能开销。实现线程安全的方式简单粗暴,就是synchronized
3. StringBuilder能力上和StringBuffer是没有区别的,但它不是线程安全的。
4. StringBuilder和StringBuffer都继承AbstractStringBuilder,也是使用字符数组,但没有final关键字,所以这两种对象是可变的。
十. 反射
1. (框架的灵魂啊我根本没用过框架哈哈哈)
反射赋予我们运行时分析类以及执行类中方法的能力,通过反射可以获取一个类所有属性和方法,也可以调用这些方法和属性
2. 优缺点
(1)
3. 应用
框架大量使用了反射机制
动态代理的实现也以来反射机制
注解也利用了反射机制
十一. 异常
1. Exception和Error的区别:exception是程序正常运行中可以预料到的意外情况,应该被捕获且进行相应的处理;error是正常情况下不太可能会出现的情况,可能会使jvm处于不可恢复的情况
两者都继承了Throwable类,exception属于程序本身可以处理的异常,可以通过catch捕获;error属于程序无法处理的错误,一般jvm会选择线程终止。
2. Try-catch-finally
Try:捕获异常
Catch:处理try捕获的异常
Finally:当在 try 块或 catch 块中遇到 return 语句时,finally 语句块将在方法返回之前被执行。
3. 使用try-with-resources来代替try-catch-finally
使用范围:需要关闭的对象(实现closeable)
Try-with-resources中,catch/finally在声明资源关闭后运行
十二. I/O
1. 序列化:数据结构转化为二进制字节流。
2. 反序列化:将二进制字节流转化为数据结构/对象
3. 不想进行序列话,使用transient关键字
4. 获取键盘输入的方法:Scanner,BufferReader
5. IO流分为InputStream/Reader(字节输入,字符输入;OutputStream/Writer(字节输出,字符输出;
6. 为什么需要区分字节流和字符流:字符流是jvm将字节转换得到的,这个过程很耗时且容易乱码;