当前位置: 首页 > article >正文

JAVA学习之JAVASE基础

集合列表ListArrayList利用空参创建的集合在底层创建一个默认长度为0的数组添加第一个元素时底层会创建一个新的长度为10的数组存满时会扩容1.5倍一次存多个元素1.5倍还不够则新创建的数组长度以实际为准LinkedList底层数据结构是双链表查询慢首位操作速度是极快的复杂度分析操作ArrayListLinkedList查询O(1)O(n)头部插入/删除O(n)O(1)尾部插入O(1)*O(1)中间插入/删除O(n)O(n)空间开销O(n)O(n)ArrayList尾部插入在扩容时为O(n)遍历方式增强for循环for-each)for (ElementType element : list) { // 处理element } ​传统forfor (int i 0; i list.size(); i) { ElementType element list.get(i); // 处理element } ​iterator迭代器IteratorElementType iterator list.iterator(); while (iterator.hasNext()) { ElementType element iterator.next(); // 处理element } ​stream流jdk8list.stream().forEach(element - { // 处理element }); ​parallelStream并行流list.parallelStream().forEach(element - { // 处理element });Iterator在底层创建一个内部类对象表示ArrayList的迭代器多次调用这个方法相当于创建多个迭代器对象如何避免并发修改异常 在使用迭代器或者增强for遍历集合过程中不要使用集合的方法去添加或者删除元素平衡二叉树规则任意节点左右子树高度差不超过1右旋左左一次右旋当前根节点左子树有节点插入导致二叉树不平衡左右先局部左旋再整体右旋右右一次左旋右左先局部右旋再整体左旋红黑树红黑树是一种自平衡的二叉查找树不是高度平衡的而是通过红黑规则实现的红黑规则每一个节点是红色或者黑色根节点是黑色的如果一个节点没有子节点或者父节点则该节点相应的指针值为Nil这些Nil视为叶节点每个叶节点Nil是黑色的如果一个节点是红色的那么他的子节点必须是黑色的不能出现两个红色节点相连的情况对每一个节点从该节点到其所有后代叶节点的简单路径上均包含相同数目的黑色节点Set特点无序存取顺序不一致不重复集合中的元素不重复无索引没有带索引的方法不能通过普通的for循环遍历也不能通过索引获取元素HashSet无序、不重复、无索引底层原理创建一个默认长度16加载因子0.75的数组数组名为table根据元素的哈希值跟数组的长度计算出存入的位置int index (数组长度-1) 哈希值;判断当前元素是否为null如果为null直接存入如果位置不为null表示有元素则调用equals方法比较属性值一样不存 不一样存入数组形成链表 JDK8以前新元素存入数组老元素在新元素下面JDK8以后新元素直接挂在老元素下面当链表长度超过8而且数组长度大于等于64时自动转换为红黑树如果集合中存储的是自定义对象必须重写hashCode和equals方法LinkedHashSet有序、不重复、无索引有序指保证存储和取出的元素顺序一致底层原理底层数据结构是哈希表每个元素额外多了一个双链表机制记录存储的顺序TreeSet可排序、不重复、无索引可排序按照元素的默认规则由小到大排序底层原理基于红黑树的数据结构实现排序增删改查性能都比较好两种排序方式自然排序Javabean类实现Comparable接口指定比较规则public int compareTo(Student o) { return this.getAge()-o.getAge(); // this:表示当前元素 // o:表示已经在红黑树存在的元素 // 返回值 // 负数表示当前要添加的元素是小的存左边 // 正数表示当前要添加的元素是大的存右边 // 0表示当前要添加的元素已经存在不存 }比较器排序创建TreeSet对象时传递比较强Comparator指定规则使用原则默认第一种如果第一种不能满足当前需求就使用第二种TreeSetStudent set new TreeSet(new ComparatorStudent() { ​ Override public int compare(Student o1, Student o2) { int io1.getAge()-o2.getAge(); return i; } });用lambda表达式简化TreeSetStudent set new TreeSet((s,p)-s.getAge()-p.getAge());复杂度分析操作HashSetTreeSetLinkedHashSet查询 (contains)O(1) 平均 O(n) 最坏O(log n)O(1) 平均插入 (add)O(1) 平均 O(n) 最坏O(log n)O(1) 平均删除 (remove)O(1) 平均 O(n) 最坏O(log n)O(1) 平均空间复杂度O(n)O(n)O(n)各Set特点HashSet:基于哈希表实现无序存储性能最优TreeSet:基于红黑树实现保持元素排序有序存储LinkedHashSet:哈希表 链表实现保持插入顺序遍历方式增强for循环for-eachfor (ElementType element : set) { // 处理element } ​Iterator迭代器IteratorElementType iterator set.iterator(); while (iterator.hasNext()) { ElementType element iterator.next(); // 处理element } ​Stream APIJava 8set.stream().forEach(element - { // 处理element }); ​parallelStream并行流set.parallelStream().forEach(element - { // 处理element }); ​MapMap集合也叫键值对集合Map集合键不可以重复值可以重复遍历方式增强for循环for-eachfor (Map.EntryK, V entry : map.entrySet()) { K key entry.getKey(); V value entry.getValue(); // 处理key和value } ​Iterator迭代器IteratorMap.EntryK, V iterator map.entrySet().iterator(); while (iterator.hasNext()) { Map.EntryK, V entry iterator.next(); K key entry.getKey(); V value entry.getValue(); // 处理key和value } ​forEach方法Java 8map.forEach((key, value) - { // 处理key和value });lambdamap.forEach((k,v)- System.out.println(k v));Stream APIJava 8map.entrySet().stream().forEach(entry - { K key entry.getKey(); V value entry.getValue(); // 处理key和value });遍历键或值单独遍历// 遍历键 for (K key : map.keySet()) { // 处理key } // 遍历值 for (V value : map.values()) { // 处理value }HashMapSet系列集合的底层就是基于Map实现的只是Set集合中的元素只要键数据不要值而已HashMap底层原理和HashSet是一样的Map实现查询(get)插入(put)删除(remove)空间复杂度HashMapO(1) 平均 O(n) 最坏O(1) 平均 O(n) 最坏O(1) 平均 O(n) 最坏O(n)TreeMapO(log n)O(log n)O(log n)O(n)LinkedHashMapO(1) 平均O(1) 平均O(1) 平均O(n)HashtableO(1) 平均 O(n) 最坏O(1) 平均 O(n) 最坏O(1) 平均 O(n) 最坏O(n)ConcurrentHashMapO(1) 平均 O(n) 最坏O(1) 平均 O(n) 最坏O(1) 平均 O(n) 最坏O(n)特点说明HashMap: 基于哈希表实现无序存储性能最优TreeMap: 基于红黑树实现按键排序存储LinkedHashMap: 哈希表链表实现保持插入顺序Hashtable: 线程安全的哈希表实现性能相对较低ConcurrentHashMap: 线程安全的现代哈希表实现支持高并发NavigableMap 常用方法键查找方法lowerKey(K key) - 返回严格小于给定键的最大键floorKey(K key) - 返回小于或等于给定键的最大键ceilingKey(K key) - 返回大于或等于给定键的最小键higherKey(K key) - 返回严格大于给定键的最小键Entry 查找方法lowerEntry(K key) - 返回严格小于给定键的最大键值对floorEntry(K key) - 返回小于或等于给定键的最大键值对ceilingEntry(K key) - 返回大于或等于给定键的最小键值对higherEntry(K key) - 返回严格大于给定键的最小键值对边界元素方法firstEntry() - 返回第一个最小的键值对lastEntry() - 返回最后一个最大的键值对pollFirstEntry() - 获取并移除第一个键值对pollLastEntry() - 获取并移除最后一个键值对导航和子集方法descendingIterator() - 返回降序键迭代器descendingMap() - 返回逆序视图的 NavigableMapheadMap(K toKey) - 返回严格小于指定键的部分视图tilMap(K fromKey) - 返回大于等于指定键的部分视图Stream流Stream流是一种可以用于操作集合或者数组数据的一套API示例ListString list2 list.stream() .filter(s - s.startsWith(张)) .filter(s - s.length() 3) .collect(Collectors.toList());获取stream流listListString s list.stream();mapStreamString s1 map.keySet().stream(); StreamInteger s2 map.values().stream(); StreamMap.EntryString, Integer s3 map.entrySet().stream();arrrayStreamInteger s1 Arrays.stream(arr); StreamInteger s2 Arrays.stream(arr); StreamInteger s3 Stream.of(arr); StreamString s4 Stream.of(张三, 李四, 王五);Stream流常用方法Stream流的终结方法Collection工具类字符集ASCII标准ASCII字符集使用一个字节存储一个字符首位是0GBK汉字编码字符集一个中文编码成两个字节的形式存储汉字的第一个字节必须是1Unicode字符集统一码也叫万国码Unicode是国际组织制定的可以容纳世界上所有文字、符号的字符集UTF-32每4个字节表示一个字符UTF-8是Unicode字符集的一种编码方式采取可变长度编码方案共分4个长度区1个字节、2个字节、3个字节、4个字节英文字符、数字等占一个字节汉字占用3个字节IO流I指input称为输入流负责把数据读到内存中O指Outout称为输出流负责写数据出去读文本适合用字符流字节流适合数据的转移比如文件复制字节流文件字节输入流FileInputStream filenew FileInputStream(1.text); byte []buf file.readAllBytes(); int len; while((lenfile.read(buf))!-1){ String strnew String(buf, 0, len); System.out.print(str); }文件字节输出流FileOutputStream filenew FileOutputStream(out.txt,true); byte[] bytes 马超.getBytes(StandardCharsets.UTF_8); file.write(bytes); file.write(\r\n.getBytes(StandardCharsets.UTF_8)); file.close();文件复制字节流非常适合文件复制public static void copyFile(String src,String dest) throws IOException { //1.创建一个文件字节输入流管道与源文件连通 FileInputStream fis new FileInputStream(src); FileOutputStream fos new FileOutputStream(dest); byte[] buffer new byte[1024]; int len; while((len fis.read(buffer))!-1){ fos.write(buffer,0,len); } fos.close(); ​ }资源释放一般用于在程序执行完成后用于资源的释放操作字符流文件字符输入流文件字符输出流缓冲流作用提高字节输入读取数据的性能原理缓冲字节输入流自带8KB的缓冲池缓冲字节输出流自带8KB缓冲池缓冲字节流缓冲字符输入流try ( Reader fr new FileReader(src); BufferedReader br new BufferedReader(fr) ) { String line; while((linebr.readLine())!null){ System.out.println(line); } }catch(Exception e){ e.printStackTrace(); }缓冲字符输出流try ( Reader fr new FileReader(src); BufferedReader br new BufferedReader(fr); Writer fwnew FileWriter(dest,true); BufferedWriter bwnew BufferedWriter(fw) ) { String line; while((linebr.readLine())!null){ bw.write(line); bw.newLine(); } }catch(Exception e){ e.printStackTrace(); }字符输入转换流解决不同编码时字符读取文本乱码问题解决思路先获取文件的原始字节流再将其按真实的字符集编码转化成字符输入流这样字符输入流中的字符就不乱码了打印流作用更方便、更高效的打印数据出去能实现打印啥就是啥PrintStream ps new PrintStream(3.text); ps.println(hello); ps.println(97);数据输出流允许把数据和其类型一并写出去IO框架多线程线程是一个程序内部的一条执行流程多线程是指从软硬件上实现的多条执行流程技术创建方式继承Thread类定义一个子类MyThread继承线程类重写run()方法创建MyThread对象调用线程对象的start()方法启动线程启动后还是执行run方法的public class Test{ public static void main(String[] args) { MyThread t1new MyThread(); t1.start(); ​ } ​ } class MyThread extends Thread{ public void run(){ for(int i0;i10;i){ System.out.println(Thread.currentThread().getName() i); } } }实现Runnable接口定义一个线程任务类MyThread实现Runnable接口重写run()方法创建MyRunnable任务对象把MyRunnable任务对象交给Thread处理​ public class Test{ public static void main(String[] args) { MyRunnable mr new MyRunnable(); Thread t1 new Thread(mr,线程1); t1.start(); } ​ } class MyRunnable implements Runnable{ public void run(){ for (int i 0; i 10; i) { System.out.println(Thread.currentThread().getName()--i); } } }或者使用匿名内部类方式public static void main(String[] args) { //方式1 Runnable r new Runnable() { Override public void run() { for (int i 0; i 5; i) { System.out.println(Thread.currentThread().getName() i); } } }; Thread tnew Thread(r); t.start(); //方式2 new Thread(() -{ for (int i 0; i 5; i) { System.out.println(Thread.currentThread().getName() i); } }).start(); }实现Callable接口优点可以返回线程执行完毕后的结果定义一个类实现Callable接口重写call方法把Callable类型的对象封装成FutureTask线程任务对象调用Thread对象的start()方法线程执行完毕后通过FutureTask对象的get方法获取线程任务执行的结果public class Test{ public static void main(String[] args) { CallableString mc new MyCallable(100); FutureTaskString ft new FutureTask(mc); Thread tnew Thread(ft); t.start(); ​ ​ try { System.out.println(ft.get()); } catch (Exception e) { e.printStackTrace(); } } ​ } class MyCallable implements CallableString { private int n; public MyCallable(int n) { this.n n; } Override public String call() throws Exception { ​ int sum0; for(int i0;in;i){ sumi; } return 0-n的和sum; } }线程安全问题多个线程同时访问一个共享资源且存在修改时会发生线程安全问题解决方法同步代码块把访问共享资源的核心代码上锁以此保证线程安全原理每次指允许一个线程加锁后进入执行完毕后自动解锁其它线程才可以进来执行使用规范建议使用共享资源作为锁对象对于实列方法建议使用this作为锁对象对于静态方法建议使用字节码类名.class对象作为锁对象public void drawMoney(double money){ String nammeThread.currentThread().getName(); synchronized (this) { if(this.moneymoney){ System.out.println(namme取钱成功取了money元); this.money-money; System.out.println(余额为this.money); }else{ System.out.println(namme取钱失败余额不足); } } }同步方法作用把共享资源的核心方法上锁以此保护线程安全public synchronized void drawMoney(double money){ String nammeThread.currentThread().getName(); if(this.moneymoney){ System.out.println(namme取钱成功取了money元); this.money-money; System.out.println(余额为this.money); }else{ System.out.println(namme取钱失败余额不足); } }lock锁public void drawMoney(double money){ try { String nammeThread.currentThread().getName(); lock.lock(); if(this.moneymoney){ System.out.println(namme取钱成功取了money元); this.money-money; System.out.println(余额为this.money); }else{ System.out.println(namme取钱失败余额不足); } } finally { lock.unlock(); } }线程池线程池就是一个可以复用的技术不使用线程池的问题创建新线程的开销是很大的并且请求过多时肯定会产生大量的线程出来这样会严重影响系统的性能。创建线程池对象使用ExecutorServixe的实现类ThreadPoolExecutor自创一个线程池对象什么时候创建临时线程新任务提交时发现核心线程都在忙任务队列也满了并且还可以创建线程此时才会创建临时线程核心线程和临时线程都很忙任务队列也满了新任务过来才会开始拒绝任务public static void main(String[] args) { ThreadPoolExecutor pool new ThreadPoolExecutor(3,5, 10,SECONDS,new ArrayBlockingQueue(3), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy()); Runnable rnew MyRunnable(); pool.execute(r);//提交任务创建第1个线程 pool.execute(r);//提交任务创建第2个线程 pool.execute(r);//提交任务创建第3个线程 pool.execute(r);//复用线程 pool.execute(r);//复用线程 pool.execute(r);//创建临时线程 pool.execute(r);//创建临时线程 pool.execute(r);//创建临时线程 pool.execute(r);//任务拒绝策略 ​ }使用Executors线程池的工具类调用方法返回不同特点的线程池对象线程池的核心线程数量和最大线程数量的配置需要根据具体的应用场景、任务类型CPU密集型或I/O密集型以及硬件资源来决定。CPU密集型任务 核心线程数CPU核心数 1 最大线程数与核心线程数相同或稍大一些 这种情况下线程数不宜过多否则会因上下文切换导致性能下降。I/O密集型任务 核心线程数CPU核心数 * 2 最大线程数可以根据任务的具体情况适当增加通常可以设置为几十到上百。 I/O操作会让线程等待因此可以配置更多的线程来提高CPU利用率。并发并行正在运行的程序是一个独立的进程线程是属于进程的一个进程可以同时运行很多个线程进程中的多个线程其实是并发和并行执行的并发并发是指在同一时间段内多个任务交替执行给人一种同时进行的感觉。它通过任务切换实现尽管在单核CPU上同一时刻只有一个任务运行但快速切换使得多个任务看似并行。并行并行是指多个任务在同一时刻真正同时执行通常需要多核处理器或多台计算机的支持。与并发不同并行任务不仅在逻辑上同时进行物理上也在同一时间执行。网络编程计算机网络中连接和通信数据的规则被称为网络协议UDP协议用户数据协议面向无连接不可靠传输的通信协议TCP协议面向连接、可靠通信目的保证数据在不可靠信道上实现可靠传输。三次握手建立连接四次挥手断开连接UDP通信一发一收public class Server { public static void main(String[] args) throws Exception { //完成UDP通信一发一收服务端开发 System.out.println(服务端启动...); //1.创建服务器Socket对象 DatagramSocket socket new DatagramSocket(8080); //2.创建数据包用于接收客户端发送的数据 byte[] bys new byte[1024*64]; DatagramPacket dp new DatagramPacket(bys, bys.length); //3.接受数据将数据封装到数据包中 socket.receive(dp); String datanew String(bys,0,dp.getLength()); System.out.println(客户端说data); } } ​public class Client { public static void main(String[] args) throws Exception { //完成UDP通信一发一收客户端开发 System.out.println(客户端启动...); //1.创建发送端对象 DatagramSocket socket new DatagramSocket(); //2.创建数据包对象封装要发送的数据 byte[] bytes 你好我是客户端.getBytes(); DatagramPacket dp new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),8080); //3.发送数据 socket.send(dp); ​ } }多发多收public class Client { public static void main(String[] args) throws Exception { //完成UDP通信一发一收客户端开发 System.out.println(客户端启动...); //1.创建发送端对象 DatagramSocket socket new DatagramSocket(); Scanner sc new Scanner(System.in); while (true) { System.out.println(请输入要发送的数据(exit)终止:); String msgsc.nextLine(); if(exit.equals(msg)){ break; } //2.创建数据包对象封装要发送的数据 byte[] bytes msg.getBytes(); DatagramPacket dp new DatagramPacket(bytes,bytes.length, InetAddress.getLocalHost(),8080); //3.发送数据 socket.send(dp); } socket.close(); ​ } }public class Server { public static void main(String[] args) throws Exception { //完成UDP通信一发一收服务端开发 System.out.println(服务端启动...); //1.创建服务器Socket对象 DatagramSocket socket new DatagramSocket(8080); //2.创建数据包用于接收客户端发送的数据 byte[] bys new byte[1024*64]; DatagramPacket dp new DatagramPacket(bys, bys.length); while (true) { ​ //3.接受数据将数据封装到数据包中 socket.receive(dp); String datanew String(bys,0,dp.getLength()); System.out.println(客户端说data); ​ String ipdp.getAddress().getHostAddress(); int portdp.getPort(); System.out.println(客户端的ipip 客户端的端口port); System.out.println(------------------------------------); } } }TCP通信一发一收public class ClientDemo { public static void main(String[] args) throws Exception { //实现TCP通信一发一收客户端开发 System.out.println(客户端启动...); //1.获取Socket管道对象请求与服务端的Socket连接 Socket socket new Socket(127.0.0.1, 9999); //2.从Socket通信管道中得到一个字节输出流 OutputStream os socket.getOutputStream(); //3.特殊数据流 DataOutputStream dos new DataOutputStream(os); dos.writeInt(1); dos.writeUTF(你好我是客户端); //4.关闭流和Socket dos.close(); } }public class ServerDemo { public static void main(String[] args) throws Exception { //实现TCP通信下一发一收服务端开发 System.out.println(服务端启动...); //1.创建服务端ServerSocket对象 ServerSocket ss new ServerSocket(9999); //2.调用accept方法阻塞等待客户端连接一旦有客户端连接accept方法就会返回一个Socket对象 Socket socket ss.accept(); //3.获取输入流读取客户端发送的数据 InputStream is socket.getInputStream(); //4.把字节输入流包装成特殊数据输入流 DataInputStream dis new DataInputStream(is); //5.读取数据 int iddis.readInt(); String msgdis.readUTF(); System.out.println(idid,msgmsg); //6.客户端的ip和端口 System.out.println(客户端的ipsocket.getInetAddress().getHostAddress()); System.out.println(客户端的端口socket.getPort()); } }多发多收public class ClientDemo2 { public static void main(String[] args) throws Exception { //实现TCP通信一发一收客户端开发 System.out.println(客户端启动...); //1.获取Socket管道对象请求与服务端的Socket连接 Socket socket new Socket(127.0.0.1, 9999); //2.从Socket通信管道中得到一个字节输出流 OutputStream os socket.getOutputStream(); //3.特殊数据流 DataOutputStream dos new DataOutputStream(os); Scanner sc new Scanner(System.in); while (true) { System.out.println(请输入要发送的内容(exit退出)); String msgsc.nextLine(); if(exit.equals(msg)){ System.out.println(客户端退出...); socket.close(); break; } dos.writeUTF(msg); } } }public class ServerDemo2 { public static void main(String[] args) throws Exception { //实现TCP通信下一发一收服务端开发 System.out.println(服务端启动...); //1.创建服务端ServerSocket对象 ServerSocket ss new ServerSocket(9999); //2.调用accept方法阻塞等待客户端连接一旦有客户端连接accept方法就会返回一个Socket对象 Socket socket ss.accept(); //3.获取输入流读取客户端发送的数据 InputStream is socket.getInputStream(); //4.把字节输入流包装成特殊数据输入流 DataInputStream dis new DataInputStream(is); while (true) { //5.读取数据 String msgdis.readUTF(); System.out.println(msgmsg); //6.客户端的ip和端口 System.out.println(客户端的ipsocket.getInetAddress().getHostAddress()); System.out.println(客户端的端口socket.getPort()); } } }public class ServerThread { public static void main(String[] args) throws Exception { //实现TCP通信下一发一收服务端开发 System.out.println(服务端启动...); //1.创建服务端ServerSocket对象 ServerSocket ss new ServerSocket(9999); while(true){ Socket socket ss.accept(); new ServerReader(socket).start(); } } }public class ServerReader extends Thread{ private Socket Socket; public ServerReader(Socket socket) { this.Socket socket; } Override public void run() { try { DataInputStream dis new DataInputStream(Socket.getInputStream()); while (true) { String msg dis.readUTF(); System.out.println(msg msg); System.out.println(客户端的ip Socket.getInetAddress().getHostAddress()); System.out.println(客户端的端口 Socket.getPort()); } } catch (Exception e) { e.printStackTrace(); System.out.println(客户端断开连接Socket.getInetAddress().getHostAddress()); } } }反射加载类并允许以编程的方式解剖类中的各种成分成员变量、方法、构造器等基本作用可以得到一个类的全部成分然后操作可以破坏封装性可以绕过泛型约束最重要的用途适合做Java的框架基本上主流的框架都会基于反射设计一些通用的功能public static void saveObject(Object obj) throws Exception { PrintStream ps new PrintStream(new FileOutputStream(5.text, true)); Class cobj.getClass(); String simpleName c.getSimpleName(); ps.println(simpleName); Field[] fields c.getDeclaredFields(); for (Field field : fields) { String fieldName field.getName(); field.setAccessible(true); Object fieldValue field.get(obj); ps.println(fieldNamefieldValue); } }注解注解是Java代码里的特殊标记作用是让其它程序根据注解信息来决定怎么执行该程序。自定义注解注解的解析元注解Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface MyTest { int count() default 1; }public class AnnotationDemo { public static void main(String[] args) throws Exception { Class c AnnotationDemo.class; AnnotationDemo adnew AnnotationDemo(); Method[] methodsc.getMethods(); for (Method method : methods) { if(method.isAnnotationPresent(MyTest.class)){ MyTest myTestmethod.getDeclaredAnnotation(MyTest.class); int count myTest.count(); for (int i 0; i count; i) { method.invoke(ad); } } } } MyTest(count 5) public void test1(){ System.out.println(test1方法执行了); } public void test2(){ System.out.println(test2方法执行了); } MyTest public void test3(){ System.out.println(test3方法执行了); } public void test4(){ System.out.println(test4方法执行了); } }动态代理public interface StarService { void sing(String name); String dance(); }Data AllArgsConstructor NoArgsConstructor public class Star implements StarService{ private String name; public void sing(String name) { System.out.println(this.name 正在唱歌); } public String dance() { System.out.println(this.name 正在跳舞); return 谢谢; } }public class ProxyUtil { public static StarService createProxy(Star star){ StarService proxy(StarService) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), star.getClass().getInterfaces(), new InvocationHandler() { Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name method.getName(); if(name.equals(sing)){ System.out.println(准备话筒收钱20w); } if(name.equals(dance)){ System.out.println(准备场地收钱100w); } return method.invoke(star, args); } }); return proxy; } }public class ProxyTest { public static void main(String[] args) { Star star new Star(洛天依); StarService proxy ProxyUtil.createProxy(star); proxy.sing(霜雪千年); System.out.println(proxy.dance()); } }加强版工具包SuppressWarnings(unchecked) public class UserUtil { public static T T createProxy(T t){ T proxy(T) Proxy.newProxyInstance(UserUtil.class.getClassLoader(), t.getClass().getInterfaces(), new InvocationHandler() { Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long start System.currentTimeMillis(); Object result method.invoke(t, args); long end System.currentTimeMillis(); System.out.println(耗时(end-start)/1000秒); return result; } }); return proxy; } }

相关文章:

JAVA学习之JAVASE基础

集合列表ListArrayList利用空参创建的集合,在底层创建一个默认长度为0的数组添加第一个元素时,底层会创建一个新的长度为10的数组存满时,会扩容1.5倍一次存多个元素,1.5倍还不够,则新创建的数组长度以实际为准LinkedLi…...

【2026年携程暑期实习- 5月10日-第四题-单数组交换】(题目+思路+JavaC++Python解析+在线测试)

题目内容 游游有两个长度同为 nnn 的整数数组 aaa 和 bbb。她会对数组...

ai llm训练数据合成说明

一、推理服务 使用llamacpp做本地推理服务,使用gguf加gpu加速。 模型使用Jackrong/Qwen3.5-9B-Claude-4.6-Opus-Reasoning-Distilled-GGUF llama-server.exe -m .\Qwen3.5-9B.Q4_K_M.gguf -ngl 99 -c 4096 --host 0.0.0.0 --port 8080 --parallel 4 -np …...

如何用Untrunc开源工具快速修复损坏视频:完整操作指南

如何用Untrunc开源工具快速修复损坏视频:完整操作指南 【免费下载链接】untrunc Restore a damaged (truncated) mp4, m4v, mov, 3gp video. Provided you have a similar not broken video. 项目地址: https://gitcode.com/gh_mirrors/unt/untrunc 你是否曾…...

FuSa DFMEA在芯片验证中的借鉴价值

功能安全(Functional Safety, FuSa)领域的DFMEA(Design Failure Mode and Effects Analysis,设计失效模式与影响分析)是一种以预防为主的系统化、结构化风险管理方法,它通过分析失效模式并优化来降低风险。…...

带式输送机托辊移动集声故障诊断与多普勒校正【附仿真】

✨ 本团队擅长数据搜集与处理、建模仿真、程序设计、仿真代码、EI、SCI写作与指导,毕业论文、期刊论文经验交流。 ✅ 专业定制毕设、代码 ✅如需沟通交流,点击《获取方式》 (1)锥麦移动集声采集策略与声学仿真分析: 针…...

Diablo Edit2:暗黑破坏神2角色编辑器完全指南,3步打造完美游戏体验

Diablo Edit2:暗黑破坏神2角色编辑器完全指南,3步打造完美游戏体验 【免费下载链接】diablo_edit Diablo II Character editor. 项目地址: https://gitcode.com/gh_mirrors/di/diablo_edit 你是否曾经在暗黑破坏神2中花费数十小时刷装备却一无所获…...

英文论文降AIGC教程:2026最新实测3款工具与逻辑重塑避坑指南

赶稿季来临,英文长稿的AI率到底该怎么降?不少同学愁的头都要秃了,不要再一个词一个词的扣了,这不仅慢,还会把好好的学术英语改得支离破碎。 坦率的讲,真正聪明的降ai,绝对不是机械替换&#xf…...

ARM TLB指令详解与虚拟化内存管理优化

1. ARM TLB指令基础与虚拟化背景 在ARM架构的虚拟化环境中,内存管理单元(MMU)通过TLB(Translation Lookaside Buffer)缓存虚拟地址到物理地址的转换结果,以提升内存访问性能。当页表发生变更时,…...

医疗设备软件设计的核心挑战与安全实践

1. 医疗设备软件设计的核心挑战医疗设备软件设计正面临着前所未有的复杂性和风险。作为一名在医疗设备行业工作多年的工程师,我亲眼见证了计算机技术如何彻底改变了这个领域。现代手术室和重症监护病房中,那些曾经独立的监护仪、输液泵和呼吸机&#xff…...

视频质量评估技术解析与ClearView系统实践

1. 视频质量评估的行业现状与技术痛点 在数字电视和流媒体爆发式增长的今天,视频质量评估(Video Quality Assessment, VQA)已成为设备制造商和内容提供商的核心竞争力指标。我从事视频处理算法开发已有八年,亲眼见证了这个领域从依…...

上午题_结构化开发

耦合基础知识...

智能体工程方法论:从AI辅助编码到可控软件开发的范式升级

1. 项目概述:从“氛围编码”到“智能体工程”的范式升级如果你和我一样,是一名长期在一线写代码的开发者,过去两年里,你肯定经历过那种“过山车”般的感觉。先是惊叹于AI助手(无论是GitHub Copilot、Cursor还是Claude …...

基于Vue3的一站式AI服务聚合平台开发与部署实战

1. 项目概述:一站式AI服务聚合平台 最近在折腾AI应用落地和商业化的事情,发现了一个挺有意思的开源项目——ZhiShuYun/HubFrontend。这本质上是一个基于Vue3开发的前端系统,但它做的事情远不止一个前端界面那么简单。它把GPT问答、Midjourne…...

基于有限状态机的LLM智能体:Haath架构解析与工程实践

1. 项目概述:一个基于状态机的自主LLM智能体如果你正在构建或使用LLM智能体,大概率遇到过这样的困境:你把所有能调用的工具、API、函数都一股脑儿塞给模型,然后满怀期待地发出指令。结果呢?模型要么在几十个选项里犹豫…...

保险科技前端开源方案Insura:动态表单与保费试算核心实现

1. 项目概述:一个面向保险行业的开源前端解决方案最近在梳理一些开源项目时,发现了一个挺有意思的仓库:Rashed-ux920/insura。从名字上拆解,“insura”显然是“Insurance”(保险)的缩写,而作者“…...

Curxy:轻量级P2P内网穿透工具的原理与实战部署指南

1. 项目概述与核心价值最近在折腾一些跨平台的文件同步和远程访问需求时,发现了一个挺有意思的项目:ryoppippi/curxy。乍一看这个名字,你可能和我最初一样有点摸不着头脑,它既不像一个常见的工具名,也不像某个知名软件…...

kagent:把 Agent 当 Pod 来管,赌的是 Agent 的最终归宿是 K8s

我们写过用 kubectl apply -f deployment.yaml 起一个 Pod,写过用 Service 把它暴露出来,写过用 Operator 监听 CRD 自动调和状态。Solo.io 那群人 2025 年初做了一个看起来很自然、但没人提早做出来的事:把同一套思路平移到 AI Agent 上——…...

一键完整网页截图终极指南:告别滚动拼接的烦恼

一键完整网页截图终极指南:告别滚动拼接的烦恼 【免费下载链接】full-page-screen-capture-chrome-extension One-click full page screen captures in Google Chrome 项目地址: https://gitcode.com/gh_mirrors/fu/full-page-screen-capture-chrome-extension …...

白炽灯非线性电阻特性在电路保护与调试中的经典应用

1. 项目概述:当白炽灯不再照明作为一名在电子工程领域摸爬滚打了十几年的老工程师,我手边的“破烂”工具箱里,除了常规的电阻、电容、芯片,还常年备着几样“非主流”玩意儿:几个不同瓦数的白炽灯泡。在很多人看来&…...

AI推理延迟超标?资源利用率不足35%?SITS2026动态编排引擎实测压测报告:单节点吞吐提升4.8倍,,附YAML配置模板

更多请点击: https://intelliparadigm.com 第一章:AI原生应用部署方案:SITS2026 SITS2026(Scalable Intelligent Training & Serving 2026)是一套面向生产环境的AI原生应用部署框架,专为大模型微服务…...

HolmesGPT 值不值得跟?把 AI SRE 的七强格局摊开看

CNCF Sandbox 在 2025-10 收了一个项目叫 HolmesGPT,定位是"开源 SRE Agent"。看着像下一个值得跟的风口——但同样进了 Sandbox 的 k8sgpt 已经 7,746 星,比它早一年;新来的 kagent 背靠 Solo.io,2,716 星只用了一年就…...

Go语言CLI工具服务化:基于JSON-RPC的进程间通信与自动化集成

1. 项目概述与核心价值最近在折腾一些自动化流程和跨平台脚本时,遇到了一个挺有意思的需求:如何让一个用Go语言写的、功能强大的命令行工具,能够被其他语言(比如Python、Node.js)或者更上层的应用(比如Web界…...

RTAB-Map实战:如何用databaseViewer分析SLAM闭环与优化你的地图质量

RTAB-Map深度优化:用databaseViewer精准诊断闭环问题与地图调优实战 当你已经能够用RTAB-Map跑通基础SLAM流程,却发现生成的地图总有些"不对劲"——走廊墙壁出现波浪形扭曲、重复区域无法正确对齐、导航时机器人总是撞上"空气墙"。这…...

OTFS系统中结构化稀疏表示与GPU优化实践

1. OTFS系统与结构化稀疏表示概述 在无线通信领域,正交时频空间(OTFS)调制技术因其在高移动性场景下的卓越性能而备受关注。与传统OFDM系统不同,OTFS将信息符号调制在时延-多普勒(DD)域,能够更好地抵抗多普勒扩展和时延扩展的影响。然而&…...

高精度正弦/余弦插值技术解析与应用

1. 高精度正弦/余弦插值技术概述在工业自动化、电机控制和精密测量领域,位置传感器是核心部件之一。这类传感器通常输出两路相位差90度的正弦和余弦模拟信号,其幅值变化与机械位置或角度呈严格对应关系。如何将这些模拟信号转换为高精度的数字位置信息&a…...

【Keras+TensorFlow+Yolo3】从零构建自定义目标检测模型:实战标注、训练与部署(TF2避坑指南)

1. 环境准备与工具安装 目标检测是计算机视觉领域的重要应用,而YOLOv3作为其中的经典算法,凭借其速度和精度的平衡备受青睐。在开始实战前,我们需要搭建好开发环境。我推荐使用Anaconda创建独立的Python环境,这样可以避免不同项目…...

Next.js App Router与React Server Components实战:构建高性能Hacker News克隆

1. 项目概述:一个基于 Next.js App Router 与 React Server Components 的 Hacker News 克隆 如果你和我一样,在过去几年里一直在用 Next.js 的 Pages Router 构建应用,那么当 App Router 和 React Server Components 这两个概念一起出现时&…...

ARM PB11MPCore USB与DVI接口设计与信号完整性分析

1. ARM PB11MPCore接口架构解析PB11MPCore作为ARM经典的嵌入式开发平台,其外设接口设计体现了工业级嵌入式系统的典型特征。我们先从整体架构入手,理解USB和DVI接口在系统中的位置。1.1 系统级接口布局开发板采用前后面板分离设计,关键接口分…...

通过curl命令直接测试Taotoken聊天接口的配置与排错指南

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 通过curl命令直接测试Taotoken聊天接口的配置与排错指南 基础教程类,为需要在无SDK环境或快速验证接口的开发者提供指导…...