Java基础
2021-04-02 16:09:37 33 举报
AI智能生成
Java基础知识脑图
作者其他创作
大纲/内容
三大特性
继承
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为
封装
隐藏对象的属性和实现细节,仅对外公开访问方法,控制在程序中属性的读和写的访问级别
多态
多态是同一个行为具有多个不同表现形式或形态的能力
抽象类和接口
抽象类
如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。如果一个类不包含抽象方法,只是用abstract修饰的话也是抽象类
接口
接口,英文称作interface,在软件工程中,接口泛指供别人调用的方法或者函数。从这里,我们可以体会到Java语言设计者的初衷,它是对行为的抽象
对比
抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法
抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的
接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法
一个类只能继承一个抽象类,而一个类却可以实现多个接口
default方法
Java8中接口中引入默认方法和静态方法,以此来减少抽象类和接口之间的差异。
现在,我们可以为接口提供默认实现的方法了,并且不用强制子类来实现它
现在,我们可以为接口提供默认实现的方法了,并且不用强制子类来实现它
内部类
静态内部类
静态内部类可以访问外部类所有的静态变量,而不可访问外部类的非静态变量;静态内部类的创建方式,new 外部类.静态内部类()
成员内部类
成员内部类可以访问外部类所有的变量和方法,包括静态和非静态,私有和公有。成员内部类依赖于外部类的实例,它的创建方式外部类实例.new 内部类()
局部内部类
定义在方法中的内部类,就是局部内部类。定义在实例方法中的局部类可以访问外部类的所有变量和方法,定义在静态方法中的局部类只能访问外部类的静态变量和方法。局部内部类的创建方式,在对应方法内,new 内部类()
匿名内部类
匿名内部类就是没有名字的内部类
JAVA只有值传递
值传递
值传递:是指在调用函数时,将实际参数复制一份传递给函数,这样在函数中修改参数时,不会影响到实际参数。其实,就是在说值传递时,只会改变形参,不会改变实参
引用传递
是指在调用函数时,将实际参数的地址传递给函数,这样在函数中对参数的修改,将影响到实际参数
深拷贝和浅拷贝
浅拷贝
对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝
实现:需要被复制类需要实现 Cloneable 接口,重写 clone 方法即可,clone 也非常简单只需要调用 object 的 clone 方法就好
深拷贝
对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝
实现:和浅拷贝的实现拷贝的方式一样,只是将对象属性重新clone一下
实现二: Serializable 接口方式也可以实现深拷贝,而且这种方式还可以解决多层克隆的问题,多层克隆就是引用类型里面又有引用类型,层层嵌套下去,用 Cloneable 方式实现还是比较麻烦的,一不小心写错了就不能实现深拷贝了,使用 Serializable 序列化的方式就需要所有的对象对实现 Serializable 接口,我们对代码进行改造,改造成序列化的方式
反射和代理
什么是反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
Class类
Class类的对象内容是你创建的类的类型信息。Class类的构造方法是private,只有JVM能创建Class实例。
获取方式
类.class,通过类的静态变量获取
Object.getClass(),通过实例的getClass()方法获取
Class.forName("java.lang.String"),通过类的全类名去获取
获取类字段
Field getField(name):根据字段名获取某个public的field(包括父类)
Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
Field[] getFields():获取所有public的field(包括父类)
Field[] getDeclaredFields():获取当前类的所有field(不包括父类)
获取类方法
Method getMethod(name, Class...):获取某个public的Method(包括父类)
Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)
Method[] getMethods():获取所有public的Method(包括父类)
Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
获取构造函数
getConstructor(类<?>... parameterTypes):获取某个public的Constructor,parameterTypes参数是以声明顺序标识构造函数的形式参数类型的类对象的数组。
getDeclaredConstructor(类<?>... parameterTypes):获取某个Constructor
getConstructors():获取所有public的Constructor
getDeclaredConstructors():获取所有Constructor
Class[] getInterfaces():获取当前类实现的所有接口
获取父类/接口
Class getSuperclass():获取父类类型
reflect类库
Field
getName():返回字段名称
getType():返回字段类型,也是一个Class实例
getModifiers():返回字段的修饰符,它是一个int,不同的bit表示不同的含义
Field.setAccessible(true),别管这个字段是不是public,一律允许访问
Field.set(Object, Object),设置字段值,其中第一个Object参数是指定的实例,第二个Object参数是待修改的值
Method
对Method实例调用invoke就相当于调用该方法,invoke的第一个参数是对象实例,即在哪个实例上调用该方法,后面的可变参数要与方法参数一致,否则将报错。调用静态方法时,第一个参数传入null
和Field类似,对于非public方法,我们虽然可以通过Class.getDeclaredMethod()获取该方法实例,但直接对其调用将得到一个IllegalAccessException。为了调用非public方法,我们通过Method.setAccessible(true)允许其调用
Constructor
过反射来创建新的实例,可以调用Class提供的newInstance()方法:Person p = Person.class.newInstance();
调用Class.newInstance()的局限是,它只能调用该类的public无参数构造方法。如果构造方法带有参数,或者不是public,就无法直接通过Class.newInstance()来调用
调用非public的Constructor时,必须首先通过setAccessible(true)设置允许访问。setAccessible(true)可能会失败
初始化对象:People people = constructor.newInstance(类<?>... parameterTypes)
代理
静态代理
实现方法:代理对象和目标对象实现同一个接口,在代理对象的构造函数中获取到目标对象实例,在实现接口的方法中在调用目标方法前后,写上增强代码
JDK动态代理
使用JDK API,动态代理利用了JDK API,动态地在内存中构建代理对象,从而实现对目标对象的代理功能。动态代理又被称为JDK代理或接口代理
与静态代理的区别:静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件。动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中
通过Proxy类创建代理对象,调用方法newInstance(),具体:static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h ),三个参数分别为:
ClassLoader loader,:指定当前目标对象使用类加载器,获取加载器的方法是固定的,通过Class.getClassLoader()获取
Class<?>[] interfaces,:目标对象实现的接口的类型,使用泛型方式确认类型,通过object.getClass().getInterfaces()或者new Class[]{Object.class}获取
InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器的方法,会把当前执行目标对象的方法作为参数传入,InvocationHandler实例通过实现InvocationHandler接口创建。在方法Object invoke(Object proxy, Method method, Object[] args)中实现代码增强
CGLib代理
CGLib动态代理是代理类去继承目标类,然后重写其中目标类的方法啊,这样也可以保证代理类拥有目标类的同名方法
与动态代理的区别
JDK动态代理强制要求实现类必须最少实现一个接口,但是CGLIB则可以要求实现类不用实现任何接口
实现方法
创建拦截器实现MethodInterceptor接口
在拦截器方法方法Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy)中实现方法增强,调用 methodProxy.invokeSuper(o, objects);方法调用目标对象的方法
创建Enhancer对象,类似于JDK动态代理的Proxy类,为Enhancer对象设置目标类的字节码文件(目标对象Class),设置回调函数(回调函数就是实现了MethodInterceptor的类实例)
调用Enhancer对象实例的create()方法创建代理对象
JDK动态代理和CGLib动态代理的区别
JDK不需要第三方库支持,CGLib必须依赖于CGLib的类库
JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理;CGLib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理
在老版本CGLIB的速度是JDK速度的10倍左右,但是CGLIB启动类比JDK慢8倍左右,但是实际上JDK的速度在版本升级的时候每次都提高很多性能,而CGLIB仍止步不前.
JDK动态代理基于接口;CGLib动态代理基于继承
Spring的AOP如何选择动态代理?
如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP,也可以强制使用CGLIB实现AOP
如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间转换
关键字
this和super
this
this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针
super
super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类
static
static的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法!
只会在类加载的时候执行一次
static变量值在类加载的时候分配空间,以后创建类对象的时候不会重新分配
被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问
访问修饰符
final、finally、finalize
final
final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表
示该变量是一个常量不能被重新赋值
示该变量是一个常量不能被重新赋值
finally
finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法finally代码块
中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码
中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码
finalize
finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调
用,当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的
最后判断
用,当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,一个对象是否可回收的
最后判断
流程控制
continue
continue 跳出本次循环,继续执行下次循环(结束正在执行的循环 进入下一个循环条件)
break
break 跳出总上一层循环,不再执行循环(结束当前的循环体)
return
return 程序返回,不再执行下面的代码(结束当前的方法 直接返回)
面向对象
五大原则
单一职责原则(SRP)
类的功能要单一
开放封闭原则(OCP)
一个模块要做到面向修改封闭,面向拓展开放
里氏替换原则(LSP)
子类可以替换父类出现在父类能够出现的任何地方
依赖倒置原则(DIP)
高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象
接口隔离原则(ISP)
使用多个专门的接口比使用单个接口要好的多
数据类型
基础数据类型
byte
字节型,1字节
short
短整型,2字节
int
整形,4字节
long
长整型,8字节
float
单精度浮点型,4字节
double
双精度浮点型,8字节
boolean
布尔型,1字节
char
字符型,2字节
包装数据类型
hashCode()与equals()
hashCode()
hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。
HashSet 如何检查重复?
当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。
如果两个对象相等,则hashcode一定也是相同的
两个对象相等,对两个对象分别调用equals方法都返回true
两个对象有相同的hashcode值,它们也不一定是相等的,因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
控制执行流程
if-else
迭代
while
do-while
与while语句相比,do-while中的语句至少会执行一次
for
foreach
针对数据和容器
跳出循环
return
跳出当前方法
break
退出循环
continue
跳出当前迭代,进行下一次迭代
0 条评论
下一页