1. IO的背景 在java的软件设计开发中,通信架构是不可避免的,我们在进行不同系统或者不同进程之间的数据交互,或者在高并发下的通信场景下都需要用到网络通信相关的技术,对于一些经验丰富的程序员来说,Java早期的网络通信架构存在一些缺陷,其中最令人恼火的是基于性能低下的同步阻塞式的I/O通信(BIO)。 随着互联网开发下通信性能的高要求,Java在2002年开始支持了非阴塞式的I/O通信技术(NIO)。大多数读者在学习网络通信相关技术的 时候,都只是接触到零碎的通信技术点,没有完整的技术体系架构,以至于对Java的通信场景总是没有清晰的解决方案。本次课程将通过大量清晰直接的案例从最基础的BlO式通信开始介绍到NIO、AIO,读者可以清晰的了解到 阻塞、非阻塞、同步、异步的现象、概念和特征以及优缺点。 本课程结合了大量的案例让读者可以快速了解每种通信架构的使用。
1. Java内部类 1.1 什么是内部类? Java中,可以将一个类定义在另外一个类(接口),或者定义在方法里面,这样的类成为内部类。 比如类Inner定义在类Outer中,此时Inner称为内部类,Outer称为外部类。 内部类一般包括如下四种: 成员内部类 方法内部类 匿名内部类 静态内部类
1. 常见的key-value格式 Java中的Map(Object o1,Object o2); Java中的Properties类(String s1,String s2); JavaScript(json)中的对象(String s,Object o); jsp中的四大属性(String s,Object o); jsp中的Cookie(String s,String s2); Java中的session,setAttribute(String s,Object o);
1. 包装类API ```java package javase.demo08.baozhaunglei; import org.junit.Test;
1. Java中创建包的格式 package 包名称.子包名称; 注意:创建包的语句必须放在当前文件的开头。
1. 返回调用方需要的值 return总是和方法之间的调用密切相关,对程序而言,方法之间的调用实际上是一种消息通信。 当调用方的方法需要被调用方返回一个指定的类型值时,那么被调用方必须明确指定返回值类型,且必须在每一个case里都使用return返回指定的类型值。
1. String两种实例化方式 字符串常量实例化,new String()构造实例化。 两种实例化方式都尝试首先去String常量池中拿值。拿不到再重新开辟堆内存和String常量池内存。直接实例化的方式对于String常量池中的同一个对象不再重新开辟堆内存,new构造方法的方式每次都会重新开辟堆内存,但是对于String常量池中的同一个String对象不会重新开辟String常量池内存。 字符串常量是匿名的String对象。 注意String的设计不同于其他类型,它采用String常量池的设计方式,有效的节省了String的内存消耗,因为任何方式开辟的String对象的值都永远存放在String常量池中: String str1="abc"; String str2="abc"; String str3=new String("abc"); 如下图: java中常见的常量池有3种: (1) class常量池:保存编译期间就确定的常量,即final类型的; (2) 运行时常量池:在JVM运行期间保存从class常量池中复制过来的副本; (3) String常量池:字符串独有的设计,就是因为它的操作很频繁且内存消耗过大。 2. String和基本包装类型不可变 String 类的内容一旦声明则不可变,只能重新创建String实例。 String字符串的内容一旦声明则不可变,除了8大基本包装类型和Sring的内容不可变,其他的引用类型内容几乎都是可变的,通过引用操作 。 即String和8大基本包装类型其堆内存空间里的值不能被修改,因为String和8大基本包装类型的成员和类被JDK团队设计成了final类型的常量,所以只能重新开辟堆内存空间保存新的值。 而其他引用类型的设计确保了同一块堆内存空间中的值是可以被修改的。 3. java中的equals()和==的区别 变量分为基本变量和引用变量,基本变量中直接存放的就是当前变量的值,而引用类型的变量中存放的是指向其堆内存空间的地址,即引用; 所以==永远比较的都是当前变量的值,对于引用类型来说需要使用equals()比较堆内存中的内容。 总的一句话:分清楚变量和对象实体;分清楚初始化变量和实例化对象,则很多问题迎刃而解! 4. String和StringBuffer的区别 String类型的变量一旦声明、其变量内容(注意是内容,指的是对象实体)将不会改变,之所以不会改变是因为任意一个字符串都是一个String类的匿名对象且成员被设计成了final类型,只要String对象的值一改变就相当于重新开辟了一块内存空间; StringBuffer类声明的对象也可以定义字符串,但是StringBuffer类中声明的字符串是可以改变的,而不会重新开辟内存空间,因为它采取了缓冲区的机制。 StringBuffer是线程安全的类;(效率偏低) StringBuilder是非线程安全的类;(效率高) 5. String、StringBuffer、StringBuilder三者区别和联系汇总 这三个类的区别主要体现在两个方面,即运行速度和线程安全这两个方面。 执行速度: StringBuilder>StringBuffer>String。 String最慢的原因: String为字符串常量,而StringBuffer和StringBuilder均为字符串变量,即String对象一旦创建之后其内容不是能改变的,如果改变,改变的也是String对象的引用地址的指向,但是后两者一旦创建其内容是可以改变的,所以StringBuffer和StringBuilder对对象进行操作是直接通过地址改变对象实体的,不用每次多开辟内存空间和回收,所以速度优于String。 线程安全方面: StringBuilder是非线程安全的类,而StringBuffer是线程安全的类。 StringBuffer和StringBuilder中都存在成员变量,而是在多线程环境中我们在使用这两个对象的时候都会存在不安全的隐患;但是如果一个StringBuffer对象在字符串缓冲区中被多个线程对象使用时,StringBuffer中的很多方法都带有的Synchronized关键字,保证了多个线程对象对共享成员变量的线程安全操作;但是StringBuilder则没有Synchronized关键字,所以对于StringBuilder的多线程操作不能保证其线程安全性。 所以要进行的操作是多线程环境下,建议使用StringBuffer;如果是单线程环境下建议使用速度较快的StringBuilder; 总结: String:适用于少量的字符串操作的情况; StringBuilder:适用于单线程环境下在字符串缓冲区进行大量字符串操作的情况; StringBuffer:使用于多线程环境下字符串缓冲区进行大量操作的情况。
1. Java中定义数组的两种方式 注意:数组在 java 底层实际上是JVM层面实现的,整个JDK中找不到数组的实现,它直接对应的就是cpu指令,数组比较经典也比较难。
1. 三大传递概念 JAVA 中三大传递(其实JAVA中只有值传递(传值),每种传递的实质都是“值”的传递,这三种划分是根据程序中“值”的不同表现形式进行划分的): 值传递:传递的是基本类型的值。 引用传递:传递的是对象的引用地址副本。 匿名对象传递:传递的是匿名对象,匿名对象本身返回的就是当前对象的内存地址副本。 每种传递都有两种方式。手工传递和方法间参数传递: 手工传递必须使用赋值运算符“=”; 参数传递是方法间调用,调用者必须将被调用者当中的形参进行实参化。
1. 向上转型 向上转型本质是类型转换的一种,属于自动转换操作。 向上转型只能发生在父子类之间,目的是将子类的实例化对象向上转换为对应的父类对象。 向上转型的父类可以是子类的直接父类,也可以是层级较多的间接父类,还可以是层级更好的接口。 子类实例化对象向上转型的本质: 向上转型为父类对象后,该对象的引用地址实际上依旧指向对应的子类对象堆内存地址;向上转型只不过是语法糖,编译器允许不同的子类对象都转换为其某个父类型。 因为子类继承了父类中的成员变量和成员方法,因此向上转型的对象真正调用的始终是对应子类里面的方法和变量,只不过如果子类没覆盖的话,这些东西将是继承自父类而来的。 通过向上转型的对象调用方法时的原则如下: (1)如果当前父类的所有子类都没有覆盖对应的方法,则此时调用的是父类的方法。 (2)如果当前父类和当前子类之间的继承链里存在某个子类覆盖了对应的方法,则此时调用的是继承链里距离当前实例化子类最近的那个子类覆盖后的方法(最常见的实际上是当前实例化子类自己覆盖了对应的而方法)。
个人独立开发项目,基于springboot 3.x starter机制提供插拔式的插件功能
基于芋道最新源码二次开发