一、网络编程
1.1 主机类
对于主机IP的获取等操作,我们可以通过Inet4Address来获取。
1.2 网络协议 - TCP/UDP协议簇
TCP:
- 流传输协议
- 可靠传输,不会丢包
- 点对点通信, 传输效率偏低。
UDP:
- 包传输协议
- 不可靠传输,会丢包
- 点对多通信, 传输效率高
1.3 TCP接口简单使用
@Testpublic void Server() throws IOException {// 创建TCP连接ServerSocket serverSocket = new ServerSocket(8899);// 监听起来Socket accept = serverSocket.accept();InputStream inputStream = accept.getInputStream();// 为了防止汉子读取读了一半导致的解析错误ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();// buffer缓冲byte[] buffer = new byte[1024];int size = 0;while ((size = inputStream.read(buffer)) != -1) {// 让byteArrayOutputStream存储数据byteArrayOutputStream.write(buffer, 0, size);}// 最后进行数据处理System.out.println(byteArrayOutputStream.toString());inputStream.close();serverSocket.close();}@Testpublic void client() throws IOException {// 获取IP地址InetAddress ip = InetAddress.getByName("127.0.0.1");// 创建TCP连接Socket socket = new Socket(ip, 8899);// 获取写入数据流OutputStream outputStream = socket.getOutputStream();outputStream.write("你好,我是客户端".getBytes());outputStream.close();socket.close();}/*** 服务器端*/@Testpublic void server() throws IOException {// 1. 创建服务器TCP, 并且绑定端口8300ServerSocket server = new ServerSocket(8300);// 2. TCP监听Socket accept = server.accept();InputStream inputStream = accept.getInputStream();// 接受客户端的请求内容ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();// 服务器接受客户端的请求byte[] buffer = new byte[1024];int size = 0;while ((size = inputStream.read(buffer)) != -1) {byteArrayOutputStream.write(buffer, 0, size);}System.out.println("接受客户端的请求内容: " + byteArrayOutputStream.toString());// 服务器从本地读取文件,返回给客户端// 服务器读取本地文件FileInputStream fileInputStream = new FileInputStream("E:\\test02.jpeg");OutputStream outputStream = accept.getOutputStream();while ((size = fileInputStream.read(buffer)) != -1) {// 返回给客户端outputStream.write(buffer, 0, size);}outputStream.flush();System.out.println("返回给客户端数据成功!");fileInputStream.close();inputStream.close();outputStream.close();}----------------------------------------------------------------------------------------/*** 客户端*/@Testpublic void client() throws IOException {InetAddress ip = InetAddress.getByName("127.0.0.1");Socket client = new Socket(ip, 8300);OutputStream outputStream = client.getOutputStream();InputStream inputStream = client.getInputStream();byte[] buffer = new byte[1024];int size = 0;// 向服务器发送请求outputStream.write("请求服务器发送图片数据".getBytes());client.shutdownOutput();// 读取服务器内容FileOutputStream fileOutputStream = new FileOutputStream("E:\\yangjing.jpeg");while ((size = inputStream.read(buffer)) != -1) {fileOutputStream.write(buffer, 0, size);}fileOutputStream.close();inputStream.close();outputStream.close();}
1.4 UDP协议使用
@Test
public void sender() throws IOException {
// 创建UDP Socker
DatagramSocket udpClient = new DatagramSocket();
InetAddress ip = InetAddress.getByName("127.0.0.1");
String data = "我是UDP协议通信";
// 创建UDP包处理
DatagramPacket datagramPacket = new DatagramPacket(data.getBytes(), 0, data.getBytes().length, ip, 8400);
udpClient.send(datagramPacket);
udpClient.close();
}
@Test
public void receiver() throws IOException {
// 创建UDP Socker
DatagramSocket udpServer = new DatagramSocket(8400);
byte[] buffer = new byte[1024];
// 创建包
DatagramPacket datagramPacket = new DatagramPacket(buffer, 0, buffer.length);
udpServer.receive(datagramPacket);
System.out.println(datagramPacket.getData().toString());
udpServer.close();
}
1.5 URL
请求路径,Java提供Url类,可以对请求的类进行访问操作。
public static void main(String[] args) throws IOException {
URL url = new URL("https://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();;
// 获取到浏览器访问的资源, 可以进行后续的操作
InputStream is = connection.getInputStream();
}
读取db.properties配置文件
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
FileInputStream fileInputStream = new FileInputStream("db.properties");
properties.load(fileInputStream);
String driverClass = properties.getProperty("prop.driverClass");
System.out.println(driverClass);
}
二、反射
2.1 反射概念
不再使用new创建对象,而是在运行阶段通过类的class获取创建对象。可以在运行阶段动态创建对象。
2.2 反射实现
1、通过构造器创建类对象。
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
// 1. 通过反射创建对象
Class<User> userClass = User.class;
Constructor<User> constructor = userClass.getConstructor(String.class, Integer.class, Long.class);
User haomengwu = constructor.newInstance("haomengwu", 12, 560L);
System.out.println(haomengwu);
// 2. 通过反射,设置对象中的内容
Field name = userClass.getDeclaredField("name");
name.set(haomengwu, "sadas");
// 3. 通过反射,获取对应的方法
Method test01 = userClass.getDeclaredMethod("test01");
test01.invoke(haomengwu);
System.out.println(haomengwu);
}
2、通过实例化的对象 .getClass()
public static void main(String[] args) throws IOException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
User user = new User();
Class<? extends User> aClass = user.getClass();
Constructor<? extends User> constructor = aClass.getConstructor(String.class, Integer.class, Long.class);
User user1 = constructor.newInstance("haomengwu", 12, 40L);
System.out.println(user1);
}
3、通过class.forName(“path”)常见对象
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
String classPath = "com.hmw.reflection.User";
Class<?> aClass = Class.forName(classPath);
Object o = aClass.newInstance();
System.out.println(o);
}
4、通过类加载器加载
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
ClassLoader classLoader = TestClass.class.getClassLoader();
String classPath = "com.hmw.reflection.User";
Class<?> aClass = classLoader.loadClass(classPath);
Object o = aClass.newInstance();
System.out.println(o);
}
除了class类对象,其他的interface、[]、enum、annotation、基本数据类型,void都是有class对象的,我们都可以使用反射创建。
一般JavaBean对象会提供空参的构造器,目的就是了反射直接能够抵用newInstance()方法创建,然后后面慢慢赋值,其次就是子类继承父类,容易实现父类。
反射使用:
// 属性
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
Class<User> userClass = User.class;
// 获取User的所有public属性,包含继承的父类
Field[] fields = userClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("------------------------------");
// 获取User的所有权限的属性,不包含父类的属性
Field[] declaredFields = userClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
// 获取权限修饰符
int modifiers = declaredField.getModifiers();
System.out.println("权限修饰符为:" + modifiers);
// 获取权限类型
Class<?> type = declaredField.getType();
System.out.println("权限类型:" + type);
// 变量名
String name = declaredField.getName();
System.out.println("变量名为:" + name);
}
}
// 方法
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
Class<User> userClass = User.class;
// 获取User类中所有public方法, 包含父类
Method[] methods = userClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("--------------------------------------");
// 获取User当前类中的所有权限的方法
Method[] declaredMethods = userClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("--------------------------------------");
// 获取该方法上的所有注解
Annotation[] annotations = declaredMethod.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(declaredMethod.getName() + "----" + annotation);
}
System.out.println("方法的权限修饰符: " + Modifier.toString(declaredMethod.getModifiers()));
System.out.println("方法的返回值类型:" + declaredMethod.getReturnType().getName());
Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.print(declaredMethod.getName() + "方法参数:" + parameterType + " ");
}
System.out.println();
// 获取方法可能抛出来的异常
Class<?>[] exceptionTypes = declaredMethod.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypes) {
System.out.print(declaredMethod.getName() + "方法可能会抛出的一场:" + exceptionType + " ");
}
System.out.println();
System.out.println("--------------------------------------");
}
}
// 构造器
public static void main7(String[] args) throws NoSuchMethodException {
Class<User> userClass = User.class;
// 获取当前类User的public构造器
Constructor<?>[] constructors = userClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("--------------------------------------");
// 获取当前类的所有权限下的构造器
Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
}
// 获取父类的泛型名称
public static void main(String[] args) throws NoSuchMethodException {
Class<User> userClass = User.class;
// 获取当前类User的父类, 不带泛型
Class<? super User> superclass = userClass.getSuperclass();
System.out.println(superclass.getName());
// 获取当前类User带泛型的父类
Type genericSuperclass = userClass.getGenericSuperclass();
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
// 获取父类的泛型名称
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
// 输出父类的泛型
System.out.println(((Class) actualTypeArguments[0]).getName());
}
// 获取User类的 包、注解、实现的接口
public static void main(String[] args) {
Class<User> userClass = User.class;
// 获取的当前类User实现的接口
Class<?>[] interfaces = userClass.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println(anInterface);
}
// 获取User类的非泛型父类的实现的非泛型接口
Class<?>[] interfaces1 = userClass.getSuperclass().getInterfaces();
// 获取当前类User的所在包
Package aPackage = userClass.getPackage();
System.out.println(aPackage);
// 获取当前类User的注解
Annotation[] annotations = userClass.getAnnotations();
}
其中,通过反射可以获取类中的所有属性和注解,包括方法的返回值、修饰符、方法名、参数、注解,以及执行等等。
// 通过反射设置属性
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException {
Class<User> userClass = User.class;
User user = userClass.newInstance();
// 默认只能够取所有的public的属性
Field score = userClass.getField("score");
score.set(user, 20L);
System.out.println(user);
// 获取私有的属性
Field name = userClass.getDeclaredField("name");
// 私有属性需要设置Accessible才可以赋值
name.setAccessible(true);
name.set(user, "haomengwu");
System.out.println(user);
// 调用静态方法
Method test03 = userClass.getMethod("test03");
test03.invoke(user, null);
// 获取到制定的 构造器
Constructor<User> declaredConstructor = userClass.getDeclaredConstructor(String.class);
declaredConstructor.setAccessible(true);
declaredConstructor.newInstance();
}
2.3 静态代理和动态代理
代理类帮助我们创建对象。并且在创建的基础上还可以做一些扩充。
静态代理:
// 基础接口
interface ClothFactory {
void produceCloth();
}
// 代理工厂类
class ProxyClothFactory implements ClothFactory {
private ClothFactory clothFactory;
public ProxyClothFactory(ClothFactory clothFactory) {
this.clothFactory = clothFactory;
}
@Override
public void produceCloth() {
System.out.println("代理工厂做一些准备工作");
clothFactory.produceCloth();
System.out.println("代理工厂做了一些后续的收尾工作");
}
}
/**
* 被代理类
*/
class NickClothFactory implements ClothFactory {
@Override
public void produceCloth() {
System.out.println("NickClothFactory做了一些操作");
}
}
class JennyClothFactory implements ClothFactory {
@Override
public void produceCloth() {
System.out.println("JennyClothFactory做一些操作");
}
}
public class StaticProxy {
public static void main(String[] args) {
NickClothFactory nickClothFactory = new NickClothFactory();
ProxyClothFactory proxyClothFactory = new ProxyClothFactory(nickClothFactory);
proxyClothFactory.produceCloth();
JennyClothFactory jennyClothFactory = new JennyClothFactory();
ProxyClothFactory proxyClothFactory1 = new ProxyClothFactory(jennyClothFactory);
proxyClothFactory1.produceCloth();
}
}
动态代理:
/**
* 基础类
*/
interface Car {
String carName();
void havior(String carName);
}
/**
* 被代理类
*/
class BaoMaCar implements Car {
@Override
public String carName() {
return "我爱你,杨靖";
}
@Override
public void havior(String carName) {
System.out.println(carName + " 车运行起来啦");
}
}
/**
* 代理工厂, 使用Proxy.newInstance()代理对象
*/
class ProxyFactory {
public static Object getProxyInstance(Object obj) {
MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
myInvocationHandler.bind(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), myInvocationHandler);
}
}
class MyInvocationHandler implements InvocationHandler {
private Object object;
public void bind(Object object) {
this.object = object;
}
// 当代理类调用方法a时,会自动调用如下代码
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 执行代理类调用的方法,也就是被代理类执行的方法
Object invoke = method.invoke(object, args);
return invoke;
}
}
public class DynamicFactory {
public static void main(String[] args) {
BaoMaCar baoMaCar = new BaoMaCar();
Car proxyInstance = (Car)ProxyFactory.getProxyInstance(baoMaCar);
// 执行被代理类的方法
System.out.println(proxyInstance.carName());
proxyInstance.havior("好萌物");
System.out.println(proxyInstance);
}
}
所以AOP切面是基于代理实现的,代理的功能很简单,主要是帮助我们调用方法。它的好处在于可以在调用方法的前后添加一些新的方法。 从而达到切面的效果。
三、Java8新特性
3.1 Lambda表达式
-> Lambda操作符 -> 左边是形参列表 -> 右边是Lambda体
Lambda的本质是一个对象的实例。

总结:
1、Lambda形参左边的参数可以省略(会自动类型推断);如果Lanbda形参列表只有一个参数, 这一对小括号()可以省略。
2、Lambda如果只有一个执行语句(可能是reuturn),则可以省略一对{}和ruturn。
本质上Lambda就是实例化一个继承接口的类对象,并且完成接口方法的重写。 如果一个类对象继承很多个接口,则会找不到继承哪个接口,从而无法实例化,使用Lambda。
3.2 函数式接口
如果一个接口只声明了一个抽象方法, 则这个接口就是函数式接口。
可以使用@FunctionalInterface校验是否为函数式接口。这是Java为了支持OOF的扩展。
虽然说Lambda在Py语言等都是函数式,Java为了支持,但又不影响自己OOP编程思想,因此Lambda在Java中是创建了匿名对象的。
如果说一个接口是函数式接口,那么这个接口就可以使用Lambda创建。 
3.3 方法引用和构造器引用
方法引用本身其实就是Lombda,创建一个对象。
使用方法引用,必须要保证=左边的参数类型和返回值和=右边的参数类型和返回值相同。
非静态方法可以被class对象和实例化对象访问,而静态方法只能被class对象访问
方法引用的本质就是重写的方法和 传入重写的方法参数和返回值相同。
// 保证了 Consumer 中的accept方法的参数和返回值类型和 println 参数和返回值相同
Consumer<String> stringConsumer = System.out::println;
// lambda
Comparator<Integer> Comparator1 = (o1, o2) -> Integer.compare(o1, o2);
// 方法引用
Comparator<Integer> comparator2 = Integer::compare;
构造器引用:
// 匿名类
Supplier<User> supplier1 = new Supplier<User>() {
@Override
public User get() {
return new User();
}
};
// Lambda
Supplier<User> supplier2 = () -> new User();
// 构造器引用
Supplier<User> supplier = User::new;
BiFunction<Integer, String, User> biFunction = new
BiFunction<Integer, String, User>() {
@Override
public User apply(Integer integer, String s) {
return new User(integer, s);
}
};
BiFunction<Integer, String, User> biFunction1 = (age, name) -> new User(age, name);
BiFunction<Integer, String, User> biFunction2 = User::new;
数组引用:
Function<Integer, String[]> function = new Function<Integer, String[]>() {
@Override
public String[] apply(Integer integer) {
return new String[integer];
}
};
Function<Integer, String[]> function1 = (length) -> new String[length];
Function<Integer, String[]> function2 = String[]::new;
牛逼程度: 数组引用 > Lambda > 匿名类 > 继承重写,调用
三、StreamAPI操作
StreamAPI是对集合的关键抽象概念,可以对相应的集合进行复杂的查找、过滤、映射数据操作。
- stream自己不会存储元素
- stream不会改变原有对象,还是返回一个新的stream
- stream操作是延迟执行的,当需要结果的时间才会真正的执行。

只要不调用中止操作,都不会执行,只要当执行了中止操作才会真正执行。 当执行了中止操作,而不会再执行操作了。
3.1 StreamAPI中间操作流
1)filter过滤流
List<User> list = new ArrayList<>();
list.add(new User(10, "haomengwu"));
list.add(new User(20, "yangjing"));
list.add(new User(30, "wang"));
Stream<User> stream = list.stream();
stream.filter(e -> e.getAge() > 20).forEach(System.out::println);
2)limit拦截流
limit(n) 保存前n个,n+1后面的不要
public static void main(String[] args) {
List<User> list = new ArrayList<>();
list.add(new User(10, "haomengwu"));
list.add(new User(20, "yangjing"));
list.add(new User(30, "wang"));
list.stream().limit(2).forEach(System.out::println);
}
3)skip拦截流
skip(n) 跳过前n个流,只保留n后面的流。
public static void main(String[] args) {
List<User> list = new ArrayList<>();
list.add(new User(10, "haomengwu"));
list.add(new User(20, "yangjing"));
list.add(new User(30, "wang"));
list.stream().skip(2).forEach(System.out::println);
}
4)distinct去重流
被包装的类需要实现equals()和hasCode(), 去重通过这个实现
public static void main(String[] args) {
List<User> list = new ArrayList<>();
list.add(new User(10, "haomengwu"));
list.add(new User(20, "yangjing"));
list.add(new User(30, "wang"));
list.add(new User(30, "wang"));
list.stream().distinct().forEach(System.out::println);
}
4)map(Function) 接受一个函数作为参数,将返回值的流作为后续操作的入参
map(Function) 返回的是Stream流,实际上就是将Function返回值作为Stream返回
public static void main(String[] args) {
List<User> list = new ArrayList<>();
list.add(new User(10, "haomengwu"));
list.add(new User(20, "yangjing"));
list.add(new User(30, "wang"));
list.add(new User(30, "wang1"));
list.stream().map(User::getAge).filter(e -> e > 10).forEach(System.out::println);
list.stream().map(User::getName).filter(e -> e.length() > 7).forEach(System.out::println);
}
5)flatmap(Function) 接受一个函数作为参数,将返回值的流作为后续操作的入参
flatMap(Function) 和map的区别在于存放的元素是Stream, 再加上外部返回的Stream, Map不好处理,flatMap便于操作。
6)sorted() 排序
自定义对象需要实现equals和hashCode。
public static void main(String[] args) {
List<String> list = Arrays.asList("aa", "cc", "bb", "dd");
list.stream().sorted().forEach(System.out::println);
List<User> listUser = new ArrayList<>();
listUser.add(new User(1, "hao"));
listUser.add(new User(2, "hao"));
listUser.add(new User(1, "zao"));
listUser.stream().sorted((e1, e2) -> {
if(e1.getAge() > e2.getAge()) {
return 1;
} else if (e1.getAge() < e2.getAge()) {
return -1;
} else {
return e1.getName().compareTo(e2.getName());
}
}).forEach(System.out::println);
}
3.3 Stream中止操作流
public static void main5(String[] args) {
List<Integer> list = Arrays.asList(1,4,5,3,2,7);
// 全部成立 返回true
boolean b = list.stream().allMatch(e -> e > 0);
System.out.println(b);
// 全部不成立 返回true
boolean b1 = list.stream().noneMatch(e -> e <= 1);
System.out.println(b1);
// 获取第一个类型
Optional<Integer> first = list.stream().findFirst();
System.out.println(first.get());
// 获取流中任意一个元素
Optional<Integer> any = list.stream().findAny();
System.out.println(any.get());
long count = list.stream().filter(e -> e > 0).count();
System.out.println(count);
}
public static void main(String[] args) {
List<User> listUser = new ArrayList<>();
listUser.add(new User(1, "hao"));
listUser.add(new User(2, "hao"));
listUser.add(new User(3, "zao"));
// 获取集合中年龄最大的值
Optional<Integer> max = listUser.stream().map(User::getAge).max((e1, e2) -> {
return Integer.compare(e1, e2);
});
Optional<Integer> max1 = listUser.stream().map(User::getAge).max(Integer::compare);
System.out.println(max.get());
// 获取集合中年龄最小的对象
Optional<User> min = listUser.stream().min((e1, e2) -> {
return Integer.compare(e1.getAge(), e2.getAge());
});
System.out.println(min.get());
}
规约操作:
使用map做映射,提取相关的数据,然后再使用reduce进行规约。对提取的数据进行总计操作。
reduce(T identity, BinaryOperator) - 将流中的元素反复结合起来,得到一个值
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
BinaryOperator<Integer> binaryOperator = new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer integer, Integer integer2) {
return Integer.sum(integer, integer2);
}
};
BinaryOperator<Integer> binaryOperatorLambda = (e1, e2) -> { return Integer.sum(e1, e2); };
BinaryOperator<Integer> binaryOperatorMethodRef = Integer::sum;
Integer reduce = list.stream().reduce(0, Integer::sum);
System.out.println("reduce = " + reduce);
List<User> userList = new ArrayList<>();
userList.add(new User(1, "h"));
userList.add(new User(10, "h"));
userList.add(new User(100, "h"));
userList.add(new User(1000, "h"));
Integer reduce1 = userList.stream().map(User::getAge).reduce(0, StreamAPITest::sum);
System.out.println(reduce1);
}
public static int sum(Integer integer, Integer integer1) {
return Integer.sum(integer, integer1);
}
收集操作:
public static void main(String[] args) {
List<User> userList = new ArrayList<>();
userList.add(new User(1, "h"));
userList.add(new User(10, "h"));
userList.add(new User(100, "h"));
userList.add(new User(1000, "h"));
List<Integer> collect = userList.stream().map(User::getAge).collect(Collectors.toList());
List<String> collect1 = userList.stream().map(User::getName).collect(Collectors.toList());
List<String> collect2 = userList.stream().map((e) -> String.valueOf(e.getAge())).collect(Collectors.toList());
}
四、Optional类
解决了空指针异常的问题。为了避免程序中出现空指针异常。
public class OptionalTest {
public static void main(String[] args) {
// optional.of(A) A不能为空
Optional<User> asd = Optional.of(new User(1, "asd", null));
System.out.println(asd);
// optional.ofNullable(B) B 可以为空
Object hehe = Optional.ofNullable(null).orElse(new User(2, "hehe", null));
System.out.println(hehe);
test0111(new User(10, "heheh", null));
}
public static void test0111(User user) {
User user1 = Optional.ofNullable(user).orElse(new User(1, "杨靖", new Integer[10]));
Integer[] arr = Optional.ofNullable(user1.getArr()).orElse(new Integer[5]);
}
}
五、JDK9、10、11新特性
jdk需要9,10,11的版本才可以使用如下功能。
