Java 知识总结
目录
1 简介
Java 是一门面向对象编程语言,不仅吸收了 C++语言的各种优点,还摒弃了 C++里难以理解的多继承、指针等概念,因此 Java 语言具有功能强大和简单易用两个特征。Java 语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 。
Java 具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点。Java 可以编写桌面应用程序、Web 应用程序、分布式系统和嵌入式系统应用程序等。
2 JAVA SE
2.1 异常体系
2.1.1 API
- Throwable 类
- Error 类
- Exception 类
- RuntimeException 类
2.1.2 自定义异常方式
实现一个类并继承异常体系中的一个类,使其可以被抛出。还可以定义构造函数用来描述这个异常类。
2.1.3 异常处理方式
- 函数内容如果抛出编译时异常,那么要么函数声明时用 throws 声明,要么使用 try catch 处理,否则编译失败。
- 如果调用到了声明异常的函数,那么要么 throws,要么 try catch,否则编译失败。
- 功能内可以解决使用 try catch 解决;解决不了使用 throws 告诉调用者。
- 多 catch 情况,多 catch 的父类 catch 放在最下面
2.2 线程体系
2.2.1 API
- Runnable 接口
- Thread 类
- Lock 接口
- Condition 接口
2.2.2 多线程的好处和弊端
- 解决了程序多个部分同时运行的问题
- 线程太多会导致效率的降低
2.2.3 开启多线程的方法
- 定义一个类继承 Thread 类,覆盖 Thread 类中的 run()方法,直接创建 Thread 类的子类线程对象,调用其 start()方法开启线程执行其 run()方法体的内容。
- 定义类实现 Runnable 接口,实现接口中的 run()方法,通过 Thread 类创建线程对象,并将 Runnable 接口的子类对象作为构造函数的参数进行传递,最后调用线程对象 start()方法开启线程。(常用)
- 使用匿名内部类复写 Thread 来调用 start()方法开启线程。或使用匿名内部类实现或 Runnable 作为参数传递给另一个匿名 Thread 对象调用 start()方法。(快速方式)
2.2.4 线程安全问题
- 前提
- 有多个线程在操作共享数据。
- 操作共享数据的代码有多条
- 原因 : 当一个线程在执行操作共享数据的多条代码中,其他代码参与了运算,并改变了共享数据的值,就会产生线程安全问题。
- 解决方法 : 同步。解决了线程的安全问题,但是相对的降低了效率,因为同步外的线程都会判断同步锁。要注意同步的多线程必须使用同一个锁。
2.2.5 多生产多消费问题解决方案
- 用 while 判断标记,解决线程获得执行权后,是否运行;用 notifyAll()唤醒线程,保证必然唤醒对方线程。(降低效率)
- 使用 jdk1.5 新增的用来代替 synchronized 和 Object 中关于线程监视操作的函数的 Lock 和 Condition 接口,只要在一个锁上创建两个监视器,然后使用 signal()方法唤醒对方监视器上的线程。
2.2.6 结束线程的方法
- 通常使用循环控制标记结束线程
- 当线程等待读不到标记时,使用线程类的 interrupt()方法,强制从等待状态唤醒,并在处理其会产生的 InterruptedException 时,令其读到结束标记。
2.3 集合体系
- Collection 接口
- List 接口(保证存取顺序,元素可以重复)
Vector 类- ArrayList 类(数组数据结构,不同步。)
- LinkedList 类(链表数据结构,不同步。)
- Set 接口(保证对象唯一)
- HashSet 类(哈希表数据结构,不同步)
- LinkedHashSet 类(保证唯一的同时,保证存取顺序)
- TreeSet 类(二叉树结构,不同步。)
- List 接口(保证存取顺序,元素可以重复)
- Map 接口(存储一些具有对应关系的数据)
Hashtable 类- HashMap 类(哈希表结构;不同步;允许 null 作为键值;)
- LinkedHashMap 类(在使用哈希表结构的同时,保证存取顺序。)
- TreeMap 类(二叉树结构;不同步)
- Iterator 接口(用于对集合进行遍历)
- Collections 类(集合排序;集合二分查找;最值查询;集合逆序;给所有元素赋值;集合随机排列;将指定集合变成同步集合;)
- Arrays 类(数组二分查找;数组复制;给所有元素赋值;排序;将数组转换位 List 集合)
2.4 IO 体系
- InputStream 抽象类(字节输入流)
- FileInputStream 类
- OutputStream 抽象类(字节输出流)
- FileOutputStream 类
- Reader 抽象类(字符输入流)
- InputStreamReader 类
- Writer 抽象类(字符输出流)
- OutputStreamWriter 类
- File 类(文件操作)
2.5 网络体系
2.6 反射体系
- Type 接口
- ParameterizedType 接口
- Class 类
- AccessibleObject 类
- Proxy 类
- InvocationHandler 接口
2.7 其他常用类
- Object
- String
- StringBuffer
- StringBuilder
- 基本数据类型对象包装类
- Byte
- Short
- Integer
- Long
- Float
- Double
- Character
- Boolean
- System
- Runtime
- Process 抽象类
- Math
- Random
- Date
- DateFormat 抽象类
- SimpleDateFormat
- Calendar 抽象
- Locale
2.8 其他常用接口
- Comparable 接口
- Comparator 接口
3 JAVA EE
3.1 Servlet
3.1.1 API
- Servlet 接口
- HttpServlet 类
- ServletConfig 接口
- 用于加载 servlet 的初始化参数
- HttpServlet 类
- ServletContext 接口
- 表示一个当前的 web 应用环境。一个 web 应用中只有一个 ServletContext 上下文对象。
- RequestDispatcher 接口
- 接收来自客户机的请求,并将它们发送到服务器上的任何资源(如 servlet、HTML 文件或 JSP 文件)。
- ServletRequest 接口
- 获取请求信息
- HttpServletRequest 接口
- ServletResponse 接口
- 设置响应信息
- HttpServletResponse
- Cookie 类
- 将会话数据保存在浏览器客户端
- Cookie 数据类型只能保存非中文字符串类型的。可以保存多个 cookie,但是浏览器一般只允许存放 300 个 Cookie,每个站点最多存放 20 个 Cookie,每个 Cookie 的大小限制为 4KB。
- HttpSession 接口
- 将会话数据保存到服务端
- Filter 接口
- FilterChain 接口
- FilterConfig 接口
- EventListener 接口
3.1.2 servlet 资源的查询过程
- 到当前 web 应用下的 web.xml 文件查找是否有匹配的 url-pattern
- 如果找到匹配的 url-pattern,则使用当前 servlet-name 的名称到 web.xml 文件中查询是否相同名称的 servlet 配置。如果找到,则取出对应的 servlet 配置信息中的 servlet-class 内容。通过反射,构造 Servlet 的对象,然后调用 Servlet 里面的方法
- 如果没有匹配的 url-pattern,则交给 tomcat 的内置的 DefaultServlet 处理。DefaultServlet 程序到 web 应用的根目录下查找是存在一个名称为"uri 字符串值"的静态文件。如果找到该文件,则读取该文件内容,返回给浏览器,如果找不到该文件,则返回 404 错误页面。
3.1.3 Sevlet 的生命周期
- 通过映射找到到 servlet-class 的内容
- 通过反射构造 FirstServlet 对象
- 创建 ServletConfig 对象,通过反射调用 init 方法
- 创建 request,response 对象,通过反射调用 service 方法
- 当 tomcat 服务器停止或 web 应用重新部署,通过反射调用 destroy 方法
3.1.4 Servlet 的多线程并发问题
- servlet 对象在 tomcat 服务器是单实例多线程的。因为 servlet 是多线程的,所以当多个 servlet 的线程同时访问了 servlet 的共享数据,如成员变量,可能会引发线程安全问题。
- 把使用到共享数据的代码块进行同步(使用 synchronized 关键字进行同步)
- 建议在 servlet 类中尽量不要使用成员变量。如果确实要使用成员,必须同步。而且尽量缩小同步代码块的范围。(哪里使用到了成员变量,就同步哪里!!),以避免因为同步而导致并发效率降低。
3.1.5 转发和重定向
- 转发
- 地址栏不会改变
- 转发只能转发到当前 web 应用内的资源
- 可以在转发过程中,可以把数据保存到 request 域对象中
- 重定向
- 地址栏会改变,变成重定向到地址
- 重定向可以跳转到当前 web 应用,或其他 web 应用,甚至是外部域名网站
- 不能再重定向的过程,把数据保存到 request 中
- 本质是浏览器重新请求一次服务器的另一个 URL
3.1.6 域对象
- HttpServletRequet 域对象
- ServletContext 域对象
- HttpSession 域对象
- PageContext 域对象
3.1.7 过滤器
- 简介
Filter 也称之为过滤器,它是 Servlet 技术中最激动人心的技术,WEB 开发人员通过 Filter 技术,对 web 服务器管理的所有 web 资源:例如 Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现 URL 级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。 - 作用
- 乱码处理
- 用户访问权限判断
- 执行过程
- 服务器创建 Filter 实例
- 执行其 init()方法
- 浏览器请求资源时,服务器调用过滤器链中的第一个过滤器的 doFilter()方法
- 在服务器调用的 doFilter()方法中,应用传入的 FilterChain 对象调用其 doFilter()方法,访问过滤器链中的下一个过滤器的 doFilter()方法或资源的 service()方法
- 调用完资源的 service()方法后会返回到最后一个调用的 doFilter()方法依次往前
- 服务器停止执行 destroy()方法
3.1.8 监听器
- 简介
Listener 用于监听 java web 程序中的事件,例如创建、修改、删除 Session、request、context 等,并触发响应的事件。
3.2 JSP
3.3 JDBC
3.4 JavaMail
4 扩展
4.1 面向对象
4.1.1 封装
- 隐藏对象的属性和实现细节,仅对外提供公共的访问方式。
- 将变化隔离;便于使用;提高重用性;提高安全性;
- 将不需要对外提供的内容都隐藏起来;把属性都隐藏提供公共方法对其访问。
4.1.2 继承
- 提高了代码的复用性;为多态提供了前提。
- 打破了封装性
- 子父类中成员变量的特点
- 子类的对象存储在堆中,包含一个父类空间用来存储父类的成员变量。
- 使用 super 来引用父类成员变量
- 子父类成员函数的特点-覆盖
- 当子类需要定义父类中某个方法的其他特有功能时,就使用覆盖。
- 静态只能覆盖静态或被静态覆盖。
- 子类方法覆盖父类方法时,子类权限必须要大于等于父类的权限
- 子父类中构造函数的特点
子类并不继承父类的构造函数;子类继承了父类获取到了父类中的内容,所有在使用父类内容之前要对其进行初始化,因此子类构造函数的第一行有个隐式的 super();;如果父类中没有定义空参的构造函数,那么子类构造函数必须使用 super 明确要调用父类中的哪个构造函数。 - 子类对象的初始化过程
- 堆内存对象的默认初始化
- 调用对应的构造函数,但并未执行初始化
- 在构造函数第一行会先执行父类的构造函数进行初始化
- 父类初始化完毕后,子类的构造函数初始化并不开始,而是先执行子类属性的显示初始化。
- 构造代码块初始化
- 最后进行子类构造函数的特定初始化
4.1.3 多态
- 表现形式 : 父类或接口引用指向子类对象
- 提高了代码的扩展性,前期定义的代码可以使用后期的内容
- 前期定义的代码不能调用后期子类的特有内容
- 前提
- 必须有关系:实现、继承;
- 必须有覆盖;
- 转型
- 向上转型限制对特有功能的访问
- 向下转型为了使用子类的特有方法
- 对于转型,自始至终都是子类对象在做着类型变化
- 类型判断 instanceof:用于判断对象的具体类型,只能用于引用数据类型的判断,通常在向下转型前用于引用类型的判断。
- 成员特点
- 变量
- 编译时参考引用变量所属的类中是否有调用的成员变量
- 运行时使用引用变量所属的类中的成员变量
- 函数
- 编译时参考引用变量所属的类中是否有调用的函数
- 运行时使用的是对象所属的类中的函数
- 静态函数
- 编译运行都参考引用变量所属的类中的方法
- 变量
4.1.4 抽象
- 抽象类
- 应用场景 : 描述类的信息不足时使用
- 抽象类不可以被实例化;子类覆盖了抽象类的抽象方法后才可以实例化;存在构造函数用于给子类初始化
- 接口
- 应用场景 : 当一个类中的方法都是抽象的时候,可以使用 interface 定义接口,接口的出现避免了单继承的局限性
- 接口是对外暴露的规则;接口是程序的功能扩展;接口的出现降低了耦合性;
- 接口中的成员都有固定的修饰符
- 全局常量:public static final
- 抽象方法:public abstract
4.2 泛型
4.2.1 简介
泛型是 JDK1.5 以后才有的;将运行时期的 ClassCastException 转到了编译时期;且可以避免频繁类型转化!
4.2.2 作用
- 设计公用的类、方法,对公用的业务实现进行抽取
- 使程序更灵活
4.2.3 泛型类
- 当类中操作的引用数据类型不确定时,就用泛型表示。
- 在创建爱泛型类对象的时候,确定类型
4.2.4 泛型方法
- 当方法操作的引用数据类型不确定时,可以给方法定义独有的泛型;当方法静态时,不能使用类上定义的泛型,如果需要使用泛型,只能定义在方法上。
- 在使用泛型方法的时候,确定泛型类型
4.2.5 泛型接口
- 当接口中操作的引用数据类型不确定时,就用泛型表示
- 如果实现接口的类是泛型类,那么类型在创建泛型类的时候确定
- 也可以在业务实现类中直接确定接口的类型
4.2.6 定义语法
- 泛型类:修饰符
class 类名<泛型类型>{code...}
;创建泛型类时,需要在左右类名后加上泛型,且必须相同不存在左边泛型限定是右边泛型限定的父类的情况。 - 泛型接口:类似于类
- 泛型方法:
修饰符 <泛型类型> 返回类型 方法名(参数列表){code...}
;使用泛型方法时,会自动根据传入的参数判断定义的泛型类型。
4.2.7 泛型限定
- 通过为引用类型的变量的泛型添加泛型限定,来限定被指向的对象能够使用的泛型定义
- ?(? extends Object)的简写 当类型不明确,又不对其进行操作时(或者只使用 Object 的方法操作),就使用通配符明确。
- (上限)? extends E
- 接受 E 类型或 E 的子类型对象,能使用 E 类型的方法。
- 当使用集合存储元素(一堆)时,作为参数被存储的集合同样需要指定泛型,为了能够存储元素及其子类对象,就需要进行泛型限定,要不然就会因为定义引用变量的泛型必须和实际参数传递的泛型定义一致的原因,导致不能存储包含元素的子类对象的集合。也就是说作为参数传递的集合泛型的定义需要能接受泛型定义为父类的集合和泛型定义为其子类的集合。
- (下限)? super E
- 接受 E 类型或者 E 类型的父类型。
- 当传递一个操作元素的需要定义泛型的参数(Comparator 等)时,为了能够接受泛型定义为自身的和泛型定义为其父类的对象(能以父类的方法操作子类的对象),就使用泛型的下限。例如,为了给存储学生的集合排序,应该能够传递给人排序的比较器。
4.2.8 擦除和补偿
- 编译时,为了兼容以前的类加载器,会将泛型去掉,生成的 class 文件是不带泛型的。
- 运行时,通过获取元素的类型进行自动的转换动作,不许要再强制转换了。
4.3 注解
4.3.1 简介
从 JDK 1.5 开始, Java 增加了对元数据(MetaData) 的支持, 也就是 Annotation(注解)。
4.3.2 作用
- 告诉编译器如何运行程序
- 简化(取代)配置文件(不便于维护:例如修改配置,要重新编译!)
4.4 包
对类文件进行分类管理;给类提供多层命名空间;包也是一种封装形式;
4.5 跨平台
对于同一个程序,在编译成中间码之后,在不同平台上使用不同的虚拟机(JVM)进行解释运行,就实现了 java 的跨平台性。
4.6 其他
- 特别自动类型转换
- Java 中涉及 byte、short 和 char 类型的运算操作首先会把这些值转换为 int 类型,然后对 int 类型值进行运算,最后得到 int 类型的结果。因此,如果把两个 byte 类型值相加,最后会得到一个 int 类型的结果。如果需要得到 byte 类型结果,必须将这个 int 类型的结果显式转换为 byte 类型。
- 因为代码中的常量通常是 int 类型,因此使用它们对 byte、short、char 进行赋值时,会有一次隐式的范围检测和向下的类型转换。
- 对于运算赋值符,它们在运算后会根据左边用来接收的变量的类型,做一次隐式的类型转换(可以向下)。
- 编译时期会完成所有全是常量的表达式的计算,包括全是字符串的拼接。
- 类加载时会创建所有字符串常量对象存入常量池
- 两同两小一大原则 :方法名和返回值列表相同,则子类返回类型小于等于父类返回类型、子类抛出异常小于等于父类异常、子类访问权限大于父类访问权限