Java基础-基础理论
基础概念
Java
和JVM
的历史
- 1996年SUN JDK1.0
Classic VM
- 纯解释运行,使用外挂进行
JIT
- 纯解释运行,使用外挂进行
- 1997年 JDK1.1发布
- AWT
- 内部类
- JDBC
- RMI
- 反射
- 1998年 JDK1.2
Solaris Exact VM
- JDK1.2开始称为Java2,三个版本
J2SE,J2EE,J2ME
- JIT解释器混合
Accutane Memory Management
精确内存管理,数据类型敏感- 提示GC性能
- JDK1.2开始称为Java2,三个版本
- 2000年 JDK1.3
Hotspot
作为默认虚拟机发布 - 2002年 JDK1.4
Classic VM
退出历史舞台- Assert
- 正则表达式
- NIO
- IPV6
- 日志API
- 加密类库
- 2004年 JDK1.5
- 泛型
- 注释
- 枚举
- 可变长的参数
- 装箱
Foreach
循环
- JDK1.6
- 脚本语言支持
- JDBC4.0
- Java解释器API
- 2011年 JDK7
- 延期项目推迟到JDK8
- G1
- 动态语言增强
- 64位系统中的压缩指针
- NIO2.0
- 泛型实例化简写
try-with-resource
- 2014年 JDK8
Lambda
表达式- 语法增强
Java
类型注解
- 2016年 JDK9
- 模块化
数据类型
基本数据类型
boolean,byte,char,short,int,float,double,long
(8种)
数据类型 | 大小/位 | 可表示范围 | 存储需求 | 默认值 |
---|---|---|---|---|
boolean |
1 | 1Byte | false | |
byte |
8 | $$-2^{7} $$~$$2^{7} -1$$ | 1Byte | 0 |
char |
16 | 0~255 | 2Byte | ‘u0000’ |
short |
16 | $$-2^{15} $$~$$2^{15} -1$$ | 2Byte | 0 |
int |
32 | $$-2^{31}$$~$$2^{31}-1$$ | 4Byte | 0 |
float |
32 | 4Byte | 0F | |
double |
64 | 8Byte | 0D | |
long |
64 | $$-2^{63}$$~$$2^{63}-1$$ | 8Byte | 0L |
-
自动类型转换方向
1
2
3char
--> int --> long --> float --> double
byte --> short
引用数据类型
- 类(
class
) - 接口(
interface
) - 数组(
[]
)
数组的定义方式
1 | int[] array = new int[]{1, 2, 3, 4}; |
字符型常量和字符串常量的区别?
- 形式上: 字符常量是单引号引起来的一个字符,字符串常量是双引号引起来的若干字符;
- 含义上: 字符常量相当于一个整型值(ASCII值),可以参加表达式运算,字符串常量代表一个地址值(字符串在内存中存放的位置)
- 占内存上: 字符常量只占2个字节,字符串常量占若干字节(至少一个字符结束标志)(char在Java中占两个字节)
构造器Construtor
是否被@Override
?
Construtor
不能被@Override
(重写),但可以Overload
(重载);
重载和重写的区别
重载
- 发生在同一个类,方法名必须相同,参数类型不同,个数不同,顺序不同,方法返回值和访问修饰符可以不同;
- 发生在编译时期;
- 口诀: 一同三异(方法名相同,参数个数,类型,顺序不同);
重写
- 发生在父子类中,方法名,参数列表必须相同;
- 返回值范围小于等于父类;
- 抛出的异常范围小于等于父类;
- 访问修饰符大于等于父类;如果父类方法访问修饰符为
private
则子类就不能重写该方法; - 口诀:一大两小
Java面向对象编程,三大特性
封装性
-
即将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而通过该类提供的方法来实现对内部信息的操作和访问;
-
另一个特点为封装在一个整体内变量及方法规定不同级别的"可见性"或访问权限
目的
- 隐藏事务内部的实现细节,以便提高安全性和简化编程
- 封装提供了合理的边界,避免外部调用者接触到内部的细节
继承性
- 新类的定义可以增加新的数据或新功能,也可以用父类的功能,但不能选择性地继承父类;
- 继承是代码复用的基础机制,继承可以看作是非常紧耦合的一种关系,父类代码修改,子类行为也会变动
- 关于继承如三点注意:
- 子类拥有父类非
private
的属性和方法 - 子类可以拥有自己属性和方法,即子类可以对父类进行扩展;
- 子类可以用自己的方式实现父类的方法;
- 子类拥有父类非
多态性
- 相同类型的变量,调用同一个方法时呈现出多种不同的行为特征;
- Java中实现多态的两种方式:
- 继承(多个子类对同一个方法重写);
- 接口(实现接口并覆盖接口中同一方法);
Java中引用变量分为两个类型
- 编译时类型
- 编译时类型有声明该变量时使用的类型决定;
- 运行时类型
- 运行时类型由实际赋值给变量的对象决定;
多态分两种
-
编译时多态: 编译时动态重载
-
运行时多态: 指一个对象可以具体多个类型,方法的覆盖;
- 理解运行多态
1
Car car = new Bus();
Car是编译时类型`,编译时检查变量类型是否存在,是否有调用的方法;
Bus是运行时类型,实行运行时访问heap中对象,调用实际的方法;
- 运行时多态由运行时类型决定的;
- 编译时多态有编译时类型决定的;
多态存在的三个条件
- 要有继承
- 要有重写
- 父类引用指向子类对象(向上转型)
实现方式
- 接口实现
- 继承父类进行方法重写
- 同一个类中进行方法重载
多态的好处
- 可替换性.多条对存在的代码具有可替换性.列如多态对圆Circle类工作,对其他任何圆形几何体,如圆环也同样工作;
- 可扩充性
- 接口性
- 灵活性
- 简化性
String
,StringBuffer
,StringBuilder
的区别是什么?String
为什么是不可变的?
String
类使用final
关键字,字符数组保存字符串private final char[] value
,所以String
对象是不可变的- 而
StringBuilder
与StringBuffer
都继承自AbstractStringBuilder
类,在AbstractStringBuilder
也是使用字符数组保存字符串char[]
,但没有final
关键字修饰,所以这两种对象是可变的 - 线程安全性
String
的对象不可变,可以理解为常量,线程安全;StringBuffer
对方法加了synchronized
或者对调用的方法加了synchronized
,所以是线程安全的;StringBuilder
没有对方法加synchronized
,所以是非线程安全的;
- 总结
- 少量数据使用
String
- 单线程操作字符串缓存区下操作大量数据使用
StringBuilder
- 多线程操作字符串缓冲区下操作大量数据使用
StringBuffer
- 少量数据使用
内部类(inner class
)
- 内部类是定义在另一个类中的类.
内部类的作用
- 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据.
- 内部类可以对同一个包中的其他类隐藏起来.
- 当想要定一个回调函数且不想编写大量代码时,使用匿名(
anonymous
)内部类比较便捷.
自动装箱与拆箱
- 装箱: 将基本类型用它们对应的引用类型包装起来;基本==>包装
- 拆箱: 将包装类型转换为基本数据类型; 包装==>基本
在一个静态方法内调用一个非静态成员为什么是非法的?
- 类的静态成员(变量或方法)属于类本身,在类加载的时候就会分配内存,可以通过类名直接访问非静态成员(变量或方法)属于类的对象,只有在类的对象产生(实例化)时才会分配内存,然后通过类的对象(实例)去访问,所以,如果一个类的静态方法去调用非静态方法或变量的时候,因为类的静态方法存在的时候,类的非静态成员可能不存在,访问一个内存中不存在的东西当然会出错;
在Java中定义一个不做事且没有参数的构造方法的作用?
- Java程序在执行子类的构造方法之前,如果没有用
super()
调用父类特定的构造方法,则会调用父类中的"没有参数的构造方法",因此,如果父类中只定义了有参数的构造方法,而子类的构造方法中又没有super()
来调用父类中特定的构造方法,则编译时将会发送错误,因为Java程序在父类中找不到没有参数的构造方法可供执行. - 解决方法:在父类中加上一个无参数的构造方法;
接口和抽象类的区别
-
Java中接口和抽象类的定义语法分别为
interface
与abstract
关键字. -
接口的所有方法在接口只能是抽象方法(
Java8
开始接口方法可以默认实现),抽象类中可以有抽象方法也可以有非抽象方法; -
接口的方法默认
public
,抽象类中的抽象方法的修饰符只能为public
或者protected
-
一个类可以实现多个接口,但类最多只能继承一个抽象类;
-
一个类实现接口的话要实现接口的所有方法,一个子类继承一个抽象类,则子类必须实现父类抽象方法,否则子类也必须定义为抽象类
-
接口可以包含变量、方法,变量被默认指定为
public static final
,方法被默认指定为public abstract
(JDK1.8
之前)抽象类可以包含属性、方法、构造方法,但是构造方法不能用于实例化,主要用途是被子类调用. -
接口不能包含初始化块,抽象类则完全可以包含初始化块;
-
接口:
JDK1.8
中对接口增加了新的特性:- 默认方法(default method):
JDK 1.8
允许给接口添加非抽象的方法实现,但必须使用default关键字修饰;定义了default的方法可以不被实现子类所实现,但只能被实现子类的对象调用;如果子类实现了多个接口,并且这些接口包含一样的默认方法,则子类必须重写默认方法; - 静态方法(static method):
JDK 1.8
中允许使用static
关键字修饰一个方法,并提供实现,称为接口静态方法.接口静态方法只能通过接口调用(接口名.静态方法名).
-
抽象类:
JDK1.8
以前抽象类的方法默认访问权限为protected
;JDK1.8
时,抽象类的方法默认访问权限为default
;
成员变量与局部变量的区别有哪些?
语法形式
- 成员变量是属于子类,而局部变量是方法中定义的变量或方法的参数;
- 成员变量可以被
public
,private
,static
等修饰符所修饰,而局部变量不能被权限修饰符及static
所修饰,但成员变量和局部变量都能被final
所修饰;
从变量在内存中的存储方式来看
- 若成员变量是用
static
修饰的那么这个成员变量是属于子类,如果没有static
修饰,这个成员变量是属于实例的; - 对象存在于堆内存,局部变量存在于栈内存;
从变量在内存中生存时间上看
- 成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失;
- 成员变量如果没有被赋值,则会自动以类型的默认值而赋值(一种情况例外被
final
修饰的成员变量也必须显示地赋值),而局部变量则不会自动赋值
对象初始化过程:
- 若在类中有静态变量和静态块,先静态后非静态,最后才是构造方法;
- 若存在继承关系,先父类后子类;
- 继承关系中,需要先父类的初始化后,才初始化子类;初始化顺序如下:
- 父类中静态成员变量和静态代码块;
- 子类中静态成员变量和静态代码块;
- 父类中普通成员变量和代码块,父类的构造函数;
- 子类中普通成员变量和代码块,子类的构造函数;
类,方法,成员变量和局部变量的可用修饰符
修饰符 | 类 | 成员方法 | 构造方法 | 域/成员变量 | 局部变量 |
---|---|---|---|---|---|
abstract |
√ | √ | - | - | - |
static |
- | √ | - | √ | - |
public |
√ | √ | √ | √ | - |
protected |
- | √ | √ | √ | - |
private |
- | √ | √ | √ | - |
synchronized |
- | √ | - | - | - |
native |
- | √ | - | - | - |
transient |
- | - | - | - | - |
volatile |
- | - | - | √ | - |
final |
√ | √ | - | √ | √ |
访问控制符权限大小
访问修饰符 | 同一个类 | 同包 | 不同包,子类 | 不同包,非子类 |
---|---|---|---|---|
private |
√ | - | - | - |
default |
√ | √ | - | - |
protected |
√ | √ | √ | √ |
public |
√ | √ | √ | √ |
什么是值传递和引用传递?
- 值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数;
- 引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数;
无论是值传递还是引用传递,其实都是一种求值策略(Evaluation strategy).在求值策略中,还有一种叫做按共享传递(call by sharing).其实Java中的参数传递严格意义上说应该是按共享传递.
按共享传递,是指在调用函数时,传递给函数的是实参的地址的拷贝(如果实参在栈中,则直接拷贝该值).在函数内部对参数进行操作时,需要先拷贝的地址寻找到具体的值,再进行操作.如果该值在栈中,那么因为是直接拷贝的值,所以函数内部对参数进行操作不会对外部变量产生影响.如果原来拷贝的是原值在堆中的地址,那么需要先根据该地址找到堆中对应的位置,再进行操作.因为传递的是地址的拷贝所以函数内对值的操作对外部变量是可见的.
为什么Java中只有值传递?
- 按值调用(call by value): 表示方法接收的是调用者提供的值;
- 按引用传递(call by reference): 表示接收的是调用者提供的变量地址.一个方法可以修改传递引用所对应的变量值,而不能修改传递引用所对应的变量值;
- Java 中只有值传递是因为变量传递时,只有变量的值被传递,而不是变量本身。对于基本数据类型,传递的是实际的值;对于引用数据类型,传递的是对象的引用
Java反射机制的作用
- 在运行时判断任意一个对象所属的类;
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法;
- 在运行时调用任意一个对象的方法
Web Service
-
Web Service(Web服务)是一种基于 Web 技术实现的分布式计算模型,它允许应用程序通过 HTTP 或 HTTPS 协议进行通信,从而在不同平台、不同编程语言之间实现数据交换和协作.
-
Web Service 提供了一种标准化的协议和格式,使得不同平台和编程语言之间的应用程序可以相互通信和交换数据.通过 Web Service,应用程序可以将自己的服务发布到 Internet 上,供其他应用程序调用,并实现跨平台、跨语言的数据交换和协作.
-
Web Service 主要包括以下三种类型:
-
SOAP(Simple Object Access Protocol,简单对象访问协议): 基于 XML 的协议,用于在 Web 上交换结构化的和扩展的信息.
-
REST(Representational State Transfer,表述性状态转移): 一种基于 HTTP 协议的架构风格,用于构建分布式 Web 应用程序.
-
XML-RPC(XML Remote Procedure Call,XML 远程过程调用): 一种基于 XML 的协议,用于远程过程调用.
-
-
Web Service 适用于分布式环境下的应用程序间的通信和数据交换,其优点包括:
-
可扩展性: Web Service 基于标准化的协议和格式,可以与不同平台和编程语言之间的应用程序相互通信和交换数据.
-
松散耦合: Web Service 提供了一种松散耦合的分布式计算模型,使得应用程序之间的通信和数据交换更加灵活和可靠.
-
互操作性: Web Service 采用标准化的协议和格式,可以与不同平台和编程语言之间的应用程序进行互操作,从而促进了数据的共享和协作.
-