java知识点

本文介绍了Java中的异常处理机制,如try-with-resources语法。讲解了JVM的类加载机制,以及如何通过反射访问private成员和调用方法。接着,深入动态代理的概念,展示了如何创建接口的动态实现。此外,讨论了注解的@Target和@Retention元注解,以及泛型的擦拭法和局限。还涵盖了集合的重写方法、IO流的同步异步操作,以及时间与日期处理中的时区知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异常

写法

编译器并不会特别地为InputStream加上自动关闭。编译器只看try(resource = …)中的对象是否实现了java.lang.AutoCloseable接口,如果实现了,就自动加上finally语句并调用close()方法

try(resource..){
}catch(){
}

JVM加载

JVM在执行Java程序的时候,并不是一次性把所有用到的class全部加载到内存,而是第一次需要用到class时才加载

反射

访问private

setAccessible(true)可以获取private
setAccessible(true)可能会失败。如果JVM运行期存在SecurityManager,那么它会根据规则进行检查,有可能阻止setAccessible(true)

调用方法

注意null和有参数
静态:Integer n = (Integer) m.invoke(null, “123”);
非静态:String r = (String) m.invoke(s, 6);
为了调用非public方法,可以通过Method.setAccessible(true)允许其调用,也可能会失败
遵循多态原则:调用实际类型的覆写方法

动态代理

动态代理(Dynamic Proxy):可以在运行期动态创建某个interface的实例,而不用实现某个实例。
动态代理实际上是JVM在运行期动态创建class字节码并加载的过程

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ReflexTest {
    public static void main(String[] args){
        InvocationHandler ih = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy,Method method,Object args[])throws Throwable{
                System.out.println(method.getName());
                System.out.println(proxy.getClass().getName());
                System.out.println(args[0]);

                return null;
            }
        };
        play p =(play)Proxy.newProxyInstance(play.class.getClassLoader(), new Class[]{play.class}, ih);
        p.catPlay();
    }
    
}
interface play{
     void catPlay();
}

注解

注解是放在Java源码的类、方法、字段、参数前的一种特殊“注释”
注解则可以被编译器打包进入class文件,因此,注解是一种用作标注的“元数据”

元数据:

元数据(Metadata),又称中介数据、中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能

@Target

类或接口:ElementType.TYPE;
字段:ElementType.FIELD;
方法:ElementType.METHOD;
构造方法:ElementType.CONSTRUCTOR;
方法参数:ElementType.PARAMETER。

@Retention

仅编译期:RetentionPolicy.SOURCE;
仅class文件:RetentionPolicy.CLASS;
运行期:RetentionPolicy.RUNTIME。

元注解

有一些注解可以修饰其他注解,这些注解就称为元注解(meta annotation)

泛型

编写泛型

注意: 编写静态方法和普通方法时要使用不同的类型,普通有T,静态就用k,区分类型。

擦拭法

定义: 虚拟机对泛型其实一无所知,所有的工作都是编译器做的
Java的泛型是由编译器在编译时实行的,编译器内部永远把所有类型T视为Object处理,但是,在需要转型的时候,编译器会根据T的类型自动为我们实行安全地强制转型。

局限

获取类的Class在转型之前,所以获取泛型的Class都是一样的Object

 MyPara<Integer> m1 = new MyPara<Integer>(23);
    MyPara<String> m2 = new MyPara<String>("ss");
    Class s1 = m1.getClass();
    Class s2 = m2.getClass();
    //MyPara<Integer>与MyPara<String> 是两个不同的类
    //等于是因为他们都变成了<MyPara<Object>
    System.out.println(s1==s2);

不能判断类型
在这里插入图片描述

通配符

<? extends T>允许调用读方法T get()获取T的引用,但不允许调用写方法set(T)传入T的引用(传入null除外);
<? super T>允许调用写方法set(T)传入T的引用,但不允许调用读方法T get()获取T的引用(获取Object除外

extends 表示T的子类,而super表示T的父类
我的理解:
extends只读(null除外):因为转入一个类型时,会因为擦拭法,变成Object然后,Object是所有的父类,不是任何的子类。
super只写(Object除外):因为擦拭法会变成Object,是所有类的父类,所以可以写,返回时只能用Object接受。
可以用PECS(生产者和消费者)原则去理解何时用extends,何时用super

无限定通配符(<?>)

它不能读也不能写,一般只用来判断是否为Null
类名<?>时所有类名的超类,都可以向上转型为类名<?>

集合

只要实现了Iterable接口的集合类都可以直接用for each循环来遍历。

重写方法和实现类

equals: List中 index(),contains()这些类型的方法要重写
equals和hashcode: Map要重写
实现Comparable:只要需要排序的,加入的类都要实现
Collections创建的集合是不可变集合,无法向其中添加或删除元素。
unmodifiableList(List) 返回的List不可变
希望把一个可变List封装成不可变List,那么,返回不可变List后,最好立刻扔掉可变List的引用(把null赋值给它既可),这样可以保证后续操作不会意外改变原始对象,从而造成“不可变”List变化了

IO流

读:从外部读进内存操作
写:从内存写入外部
File 可以表示一个目录和文件,
Out/InputStream 读取文件字节
Writer/Reader 读取字符串
几乎所有new的子类都是input和output超类
File传入inputStream再传入Buffer再传入GZIinput 这种叫做Filter模式(或者装饰器模式:Decorator)

字节与字符转换

Reader是带编码转换器的InputStream,它把byte转换为char,而Writer就是带编码转换器的OutputStream,它把char转换为byte并输出。

InputStream input = new FileInputStream("src/readme.txt");
// 变换为Reader:
Reader reader = new InputStreamReader(input, "UTF-8");

Reader需要从InputStream中读入字节流(byte),然后,根据编码设置,再转换为char就可以实现字符流。如果我们查看FileReader的源码,它在内部实际上持有一个FileInputStream。

同步和异步

同步IO是指,读写IO时代码必须等待数据返回后才继续执行后续代码,它的优点是代码编写简单,缺点是CPU执行效率低。

而异步IO是指,读写IO时仅发出请求,然后立刻执行后续代码,它的优点是CPU执行效率高,缺点是代码编写复杂。

Java标准库的包java.io提供了同步IO,而java.nio则是异步IO

可以设置编码的类

FileReader(‘路径’,StandardCharsets.UTF_8)

Print*类

System.out是标准输出;
System.err是标准错误输出。

我们经常使用的System.out.println()实际上就是使用PrintStream打印各种数据。其中,System.out是系统默认提供的PrintStream,表示标准输出:

Files

从Java 7开始,提供了Files和Paths这两个工具类,能极大地方便我们读写文件。
缺点:
Files提供的读写方法,受内存限制,只能读写小文件,例如配置文件等,不可一次读入几个G的大文件。读写大型文件仍然要使用文件流,每次只读写一部分文件内容。

时间与日期

时区

一种

是以GMT或者UTC加时区偏移表示,例如:GMT+08:00或者UTC+08:00表示东八区

二种

另一种是缩写,例如,CST表示China Standard Time,也就是中国标准时间。但是CST也可以表示美国中部时间Central Standard Time USA,因此,缩写容易产生混淆,我们尽量不要使用缩写。

三种

最后一种是以洲/城市表示,例如,Asia/Shanghai,表示上海所在地的时区。特别注意城市名称不是任意的城市,而是由国际标准组织规定的城市

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值