网络编程
计算机网络:是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程:就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
UDP传输
- 发送Send
- 创建DatagramSocket, 随机端口号
- 创建DatagramPacket, 指定数据, 长度, 地址, 端口
- 使用DatagramSocket发送DatagramPacket
- 关闭DatagramSocket
- 接收Receive
- 创建DatagramSocket, 指定端口号
- 创建DatagramPacket, 指定数组, 长度
- 使用DatagramSocket接收DatagramPacket
- 关闭DatagramSocket
- 从DatagramPacket中获取数据
- 接收方获取ip和端口号
- String ip = packet.getAddress().getHostAddress();
- int port = packet.getPort();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException;
public class Demo1_Send { public static void main(String[] args) throws Exception { String str = "what are you 弄啥呢?"; DatagramSocket socket = new DatagramSocket(); DatagramPacket packet = new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666); socket.send(packet); socket.close(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException;
public class Demo1_Receive { public static void main(String[] args) throws Exception { DatagramSocket socket = new DatagramSocket(6666); DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); socket.receive(packet); byte[] arr = packet.getData(); int len = packet.getLength(); System.out.println(new String(arr,0,len)); socket.close(); } }
|
UDP传输优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; import java.util.Scanner;
public class Demo2_Send { public static void main(String[] args) throws Exception { Scanner sc = new Scanner(System.in); DatagramSocket socket = new DatagramSocket(); while(true) { String line = sc.nextLine(); if("quit".equals(line)) { break; } DatagramPacket packet = new DatagramPacket(line.getBytes(), line.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666); socket.send(packet); } socket.close(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.SocketException;
public class Demo2_Receive { public static void main(String[] args) throws Exception { DatagramSocket socket = new DatagramSocket(6666); DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); while(true) { socket.receive(packet); byte[] arr = packet.getData(); int len = packet.getLength(); String ip = packet.getAddress().getHostAddress(); int port = packet.getPort(); System.out.println(ip + ":" + port + ":" + new String(arr,0,len)); } } }
|
UDP传输多线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; import java.util.Scanner;
public class Demo3_MoreThread { public static void main(String[] args) { new Receive().start(); new Send().start(); } }
class Receive extends Thread { public void run() { try { DatagramSocket socket = new DatagramSocket(6666); DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); while(true) { socket.receive(packet); byte[] arr = packet.getData(); int len = packet.getLength(); String ip = packet.getAddress().getHostAddress(); int port = packet.getPort(); System.out.println(ip + ":" + port + ":" + new String(arr,0,len)); } } catch (IOException e) { e.printStackTrace(); } } }
class Send extends Thread { public void run() { try { Scanner sc = new Scanner(System.in); DatagramSocket socket = new DatagramSocket(); while(true) { String line = sc.nextLine(); if("quit".equals(line)) { break; } DatagramPacket packet = new DatagramPacket(line.getBytes(), line.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666); socket.send(packet); } socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
|
TCP协议
- 客户端
- 创建Socket连接服务端(指定ip地址,端口号)通过ip地址找对应的服务器
- 调用Socket的getInputStream()和getOutputStream()方法获取和服务端相连的IO流
- 输入流可以读取服务端输出流写出的数据
- 输出流可以写出数据到服务端的输入流
- 服务端
- 创建ServerSocket(需要指定端口号)
- 调用ServerSocket的accept()方法接收一个客户端请求,得到一个Socket
- 调用Socket的getInputStream()和getOutputStream()方法获取和客户端相连的IO流
- 输入流可以读取客户端输出流写出的数据
- 输出流可以写出数据到客户端的输入流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException;
public class Demo1_Client { public static void main(String[] args) throws UnknownHostException, IOException { Socket socket = new Socket("127.0.0.1", 12345); InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); byte[] arr = new byte[1024]; int len = is.read(arr); System.out.println(new String(arr,0,len)); os.write("学习挖掘机哪家强?".getBytes()); socket.close(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;
public class Demo1_Server { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(12345); Socket socket = server.accept(); InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); os.write("百度一下你就知道".getBytes()); byte[] arr = new byte[1024]; int len = is.read(arr); System.out.println(new String(arr,0,len)); socket.close(); } }
|
多线程服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.net.Socket; import java.net.UnknownHostException;
public class Demo2_Client { public static void main(String[] args) throws UnknownHostException, IOException { Socket socket = new Socket("127.0.0.1", 12345); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream()); System.out.println(br.readLine()); ps.println("我想报名黑马程序员"); System.out.println(br.readLine()); ps.println("大哭!!!能不能给次机会"); socket.close(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.net.ServerSocket; import java.net.Socket;
public class Demo2_Server { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(12345); while(true) { final Socket socket = server.accept(); new Thread() { public void run() { try { BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream()); ps.println("欢迎咨询黑马程序员"); System.out.println(br.readLine()); ps.println("不好意思,爆满了"); System.out.println(br.readLine()); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } } }
|
反射
类的加载概述和加载时机
类的加载概述
加载时机
- 创建类的实例
- 访问类的静态变量,或者为静态变量赋值
- 调用类的静态方法
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类
类加载器的概述和分类
类加载器的概述:负责将.class文件加载到内存中,并为之生成对应的Class对象。
类加载器的分类
Bootstrap ClassLoader
: 根类加载器
Extension ClassLoader
: 扩展类加载器
Sysetm ClassLoader
: 系统类加载器
类加载器的作用
Bootstrap ClassLoader
: 根类加载器
- 也被称为引导类加载器,负责Java核心类的加载
- 比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
Extension ClassLoader
扩展类加载器
- 负责JRE的扩展目录中jar包的加载。
- 在JDK中JRE的lib目录下ext目录
Sysetm ClassLoader
系统类加载器
- 负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径
反射
反射概述
- JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
- 对于任意一个对象,都能够调用它的任意一个方法和属性;
- 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
- 要想解剖一个类,必须先要获取到该类的字节码文件对象。
- 而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。
三种方式
- Object类的getClass()方法,判断两个对象是否是同一个字节码文件
- 静态属性class,锁对象
- Class类中静态方法forName(),读取配置文件

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import com.heima.bean.Person;
public class Demo1_Reflect { public static void main(String[] args) throws ClassNotFoundException { Class clazz1 = Class.forName("com.heima.bean.Person"); Class clazz2 = Person.class; Person p = new Person(); Class clazz3 = p.getClass(); System.out.println(clazz1 == clazz2); System.out.println(clazz2 == clazz3); } }
|
Class.forName()读取配置文件
使用多态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class Demo2_Reflect { public static void main(String[] args) throws Exception { Juicer j = new Juicer(); j.run(new Apple()); j.run(new Orange()); } }
interface Fruit { public void squeeze(); } class Apple implements Fruit { public void squeeze() { System.out.println("榨出一杯苹果汁儿"); } }
class Orange implements Fruit { public void squeeze() { System.out.println("榨出一杯橘子汁儿"); } }
class Juicer { public void run(Fruit f) { f.squeeze(); } }
|
使用反射
1 2 3 4 5 6 7 8 9 10 11
| public class Demo2_Reflect { public static void main(String[] args) throws Exception { Juicer j = new Juicer(); BufferedReader br = new BufferedReader(new FileReader("config.properties")); Class clazz = Class.forName(br.readLine());
Fruit f = (Fruit) clazz.newInstance(); j.run(f); } }
|
这样我们不必要修改代码 , 直接修改配置文件即可
通过反射获取带参构造方法 :Constructor
Constructor
Class类的newInstance()
方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了,可以调用Class类的getConstructor(String.class,int.class)
方法获取一个指定的构造函数 , 然后再调用Constructor类的newInstance("张三",20)
方法创建对象
getConstructor(String.class,int.class)
: 获取有参构造
newInstance("张三",20)
: 创建对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import java.lang.reflect.Constructor; import com.heima.bean.Person;
public class Demo3_Constructor { public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.heima.bean.Person"); Constructor c = clazz.getConstructor(String.class,int.class); Person p = (Person) c.newInstance("张三",23); System.out.println(p); } }
|
通过反射获取成员变量 : Field
getField(String)
: 获取公共属性
getDeclaedField("name")
: 获取私有属性
set(obj, "李四")
: 设置属性
setAccessible(true)
: 设置访问权限(如果是私有的需要先设置访问权限)
get(obj)
: 获取指定对象中该字段的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import java.lang.reflect.Constructor; import java.lang.reflect.Field;
import com.heima.bean.Person;
public class Demo4_Field { public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.heima.bean.Person"); Constructor c = clazz.getConstructor(String.class,int.class); Person p = (Person) c.newInstance("张三",23); Field f = clazz.getDeclaredField("name"); f.setAccessible(true); f.set(p, "李四"); System.out.println(p); } }
|
封装成方法 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| import java.lang.reflect.Field;
public class Test3 { public static void main(String[] args) throws Exception { Student s = new Student("张三", 23); System.out.println(s); Tool t = new Tool(); t.setProperty(s, "name", "李四"); System.out.println(s); } }
public class Tool { public void setProperty(Object obj, String propertyName, Object value) throws Exception { Class clazz = obj.getClass(); Field f = clazz.getDeclaredField(propertyName); f.setAccessible(true); f.set(obj, value); } }
class Student { private String name; private int age; public Student() { super(); } public Student(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } }
|
通过反射获取方法 : Method
Class.getMethod(String, Class...)
: 获取类中公有方法
-
Class.getDeclaredMethod(String, Class...)
: 获取类中的私有方法
invoke(Object, Object...)
: 调用已经获取的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import java.lang.reflect.Constructor; import java.lang.reflect.Method;
import com.heima.bean.Person;
public class Demo5_Method { public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.heima.bean.Person"); Constructor c = clazz.getConstructor(String.class,int.class); Person p = (Person) c.newInstance("张三",23); Method m = clazz.getMethod("eat"); m.invoke(p); Method m2 = clazz.getMethod("eat", int.class); m2.invoke(p, 10); } }
|
封装为方法 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader;
public class Test2 { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new FileReader("xxx.properties")); Class clazz = Class.forName(br.readLine()); DemoClass dc = (DemoClass) clazz.newInstance(); dc.run(); } }
public class DemoClass { public void run() { System.out.println("welcome to heima!"); } }
|
通过反射越过泛型检查
泛型只在编译期有效,在运行期会被擦除掉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import java.lang.reflect.Method; import java.util.ArrayList;
public class student2 { public static void main(String[] args) throws Exception { ArrayList<Integer> list = new ArrayList<>(); list.add(111); list.add(222); Class clazz = Class.forName("java.util.ArrayList"); Method m = clazz.getMethod("add", Object.class); m.invoke(list, "abc"); System.out.println(list); } }
|
动态代理
概述:本来应该自己做的事情,请了别人来做,被请的人就是代理对象。
举例:春节回家买票让人代买
动态代理其实就是通过反射来生成一个代理
在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib,Proxy类中的方法创建动态代理类对象
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
最终会调用InvocationHandler的方法
InvocationHandler Object invoke(Object proxy,Method method,Object[] args)
示例 :
User类要实现add()
和delete()
两个方法.
执行这两个方法时都需要进行权限校验
和日志记录
一般写法 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class UserImp implements User {
@Override public void add() { System.out.println("权限校验"); System.out.println("添加功能"); System.out.println("日志记录"); }
@Override public void delete() { System.out.println("权限校验"); System.out.println("删除功能"); System.out.println("日志记录"); } }
|
上面写法缺陷就是 :
- 权限校验和日志记录其实和
add()
和delete()
方法并没有什么关系 .
- 于是想将这两个方法独立出去
- 在python中一般使用装饰器 , 在Java中可以使用动态代理
动态代理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class Test { public static void main(String[] args) { UserImp ui = new UserImp(); ui.add(); ui.delete();
MyInvocationHandler m = new MyInvocationHandler(ui); User u = (User)Proxy.newProxyInstance(ui.getClass().getClassLoader(), ui.getClass().getInterfaces(), m); u.add(); u.delete();
} }
public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { this.target = target; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("权限校验"); method.invoke(target, args); System.out.println("日志记录"); return null; } }
public class UserImp implements User { @Override public void add() { System.out.println("添加功能"); }
@Override public void delete() { System.out.println("删除功能"); } }
|
模版(Template)设计模式
枚举
自定义枚举类
示例一 : 空参构造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Demo1_Enum { public static void main(String[] args) { Week mon = Week.MON; Week tue = Week.TUE; Week wed = Week.WED; System.out.println(mon); } }
public class Week { public static final Week MON = new Week(); public static final Week TUE = new Week(); public static final Week WED = new Week(); private Week(){} }
|
示例二 : 有参构造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class Demo1_Enum { public static void main(String[] args) { Week2 mon = Week2.MON; System.out.println(mon.getName()); } }
public class Week { private String name; public static final Week MON = new Week("星期一"); public static final Week TUE = new Week("星期二"); public static final Week WED = new Week("星期三");
private Week(String name){ this.name = name; }
public String getName(){ return name; } }
|
示例三 : 匿名类内部方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class Demo1_Enum { public static void main(String[] args) { Week3 mon = Week3.MON; mon.show(); } }
public abstract class Week3 { private String name;
public static final Week3 MON = new Week3("星期一") { public void show() { System.out.println("星期一"); } }; public static final Week3 TUE = new Week3("星期二"){ public void show() { System.out.println("星期二"); } }; public static final Week3 WED = new Week3("星期三"){ public void show() { System.out.println("星期三"); } }; private Week3(String name){ this.name = name; } public String getName() { return name; } public abstract void show(); }
|
通过enum实现枚举类
- 定义枚举类要用关键字
enum
- 所有枚举类都是Enum的子类
- 枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略
- 枚举类可以有构造器,但必须是private的,它默认的也是private的。
- 枚举类也可以有抽象方法,但是枚举项必须重写该方法
- 枚举在switch语句中的使用
示例一 : 空参构造
1 2 3 4 5 6 7 8 9 10 11
| public class Demo1_Enum { public static void main(String[] args) { Week mon = Week.MON; System.out.println(mon); } }
public enum Week { MON,TUE,WED; }
|
示例二 : 有参构造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class Demo1_Enum { public static void main(String[] args) { Week2 mon = Week2.MON; System.out.println(mon.getName()); } }
public enum Week2 { MON("星期一"),TUE("星期二"),WED("星期三"); private String name; private Week2(String name) { this.name = name; } public String getName() { return name; } public String toString() { return name; } }
|
示例三 : 匿名类内部方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public class Demo1_Enum { public static void main(String[] args) { Week3 mon = Week3.MON; mon.show(); } }
public enum Week3 { MON("星期一"){ public void show() { System.out.println("星期一"); } },TUE("星期二"){ public void show() { System.out.println("星期二"); } },WED("星期三"){ public void show() { System.out.println("星期三"); } }; private String name; private Week3(String name) { this.name = name; } public String getName() { return name; } public abstract void show(); }
|
示例四 : 使用switch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public class Demo1_Enum { public static void main(String[] args) { Week3 mon = Week3.TUE; switch (mon) { case MON: System.out.println("星期一"); break; case TUE: System.out.println("星期二"); break; } } }
public enum Week3 { MON("星期一"){ public void show() { System.out.println("星期一"); } },TUE("星期二"){ public void show() { System.out.println("星期二"); } },WED("星期三"){ public void show() { System.out.println("星期三"); } }; private String name; private Week3(String name) { this.name = name; } public String getName() { return name; } public abstract void show(); }
|
枚举类的常见方法
int ordinal()
int compareTo(E o)
String name()
String toString()
<T> T valueOf(Class<T> type,String name)
values()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class Demo2_Enum { public static void main(String[] args) { Week2 mon = Week2.MON; Week2 tue = Week2.TUE; Week2 wed = Week2.WED; System.out.println(mon.ordinal()); System.out.println(tue.ordinal()); System.out.println(wed.ordinal()); System.out.println(mon.compareTo(tue)); System.out.println(mon.compareTo(wed)); System.out.println(mon.name()); System.out.println(mon.toString()); } }
public enum Week2 { MON("星期一"),TUE("星期二"),WED("星期三"); private String name; private Week2(String name) { this.name = name; } public String getName() { return name; } public String toString() { return name; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class Demo2_Enum { public static void main(String[] args) { Week2 mon = Week2.valueOf(Week2.class, "MON"); System.out.println(mon); Week2[] arr = Week2.values(); for (Week2 week2 : arr) { System.out.println(week2); } } }
public enum Week2 { MON("星期一"),TUE("星期二"),WED("星期三"); private String name; private Week2(String name) { this.name = name; } public String getName() { return name; } public String toString() { return name; } }
|
JDK7新特性
- 二进制字面量
- 数字字面量可以出现下划线
- switch 语句可以用字符串
- 泛型简化,菱形泛型
- 异常的多个catch合并,每个异常用或|
- try-with-resources 语句,1.7版标准的异常处理代码
1 2 3 4 5 6
| public class Demo1_JDK7 { public static void main(String[] args) { System.out.println(0b110); System.out.println(100_000); } }
|
JDK8的新特性
接口中可以定义有方法体的方法,
- 如果是非静态,必须用default修饰
- 如果是静态的就不用了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class student3 { public static void main(String[] args) { Demo d = new Demo(); d.print();
Inter.method();
Demo d = new Demo(); d.run(); } }
interface Inter { public default void print() { System.out.println("hello world"); } public static void method() { System.out.println("static method"); } }
class Demo implements Inter { public void run() { int num = 10; class Inner { public void func() { System.out.println(num); } }
Inner i = new Inner(); i.fun(); } }
|
局部内部类在访问他所在方法中的局部变量必须用final修饰,为什么?
因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用