我们知道逻辑控制一般有 3 种:顺序执行: 就是按顺序一步步执行。条件判断: 这个就是我们 Java 中的if/else和switch/case。循环语句: 跟 Java 中一样还是while和for.Tips: 虽然 Groovy 的逻辑控制和 Java 中是一样的,但是 Groovy 又扩展了一些新功能。其中条件语句的if/else和循环语句的while与 Java 中是一样的,但是条件语句的switch/case和循环语句中的for, Groovy 在 Java 的基础上做了扩展。
在上一个章节,我们介绍了如何创建了一个 Java 项目。在本章节,让我们来看看如何在Java项目中创建我们的 Java 类以及运行我们的 Java 文件。
Linux 和 Mac 下的配置方式比较类似,都是通过修改配置文件完成。Linux下修改~/.bashrc,而 Mac下是修改~/.bash_profile。在配置文件上添加:export JAVA_HOME=/Users/imooc/java/jdk1.8export PATH=$PATH:/Users/imooc/java/jdk1.8/bin在平台上配置完成之后打开终端命令行,输入:java -version能够查看 Java 的版本号,即表示配置成功。
Kotlin 中还有一些其他的预置注解,在这里就不再一一演示了,知道它们的作用即可。@Transient:该注解充当了 Java 中的 transient 关键字;@Strictfp:该注解充当了 Java 中的 strictfp 关键字;@Synchronized:该注解充当了 Java 中的 synchronized 关键字;@Volatile:该注解充当了 Java 中的 volatile 关键字。
在前面的小节中,我们相继介绍了集中应用广泛的统一身份认证规范:OAuth2.0,SAML2.0 和 CAS。本节我们介绍一种 Java 早期的安全框架,已经如何用 Spring Security 集成 JAAS。JAAS 是「Java Authentication and Authorization Service」 的缩写,其中文含义为「基于 Java 的认证和授权服务」。JAAS 提供了灵活的弹性的机制保护了 Java 客户端程序和 Java 服务端程序的安全。Spring Security 提供了 JAAS 的集成功能。
使用 rpm 命令安装刚刚下载好的安装包。执行命令:rpm -ivh jdk-14_linux-x64_bin.rpm安装过程如下:安装成功后,输入 java -version来验证是否安装成功:[root@Colorful ~]# java -versionjava version "14" 2020-03-17Java(TM) SE Runtime Environment (build 14+36-1461)Java HotSpot(TM) 64-Bit Server VM (build 14+36-1461, mixed mode, sharing)屏幕输出了如上内容,表示我们已经成功在 Linux 主机上安装了 Java。
打开 Mac 终端应用,在终端输入如下命令可以查看Java 15的安装目录:$ /usr/libexec/java_home -v 15/Library/Java/JavaVirtualMachines/jdk-15.0.1.jdk/Contents/Home请记住这里的安装目录:/Library/Java/JavaVirtualMachines/jdk-15.0.1.jdk/Contents/Home,下面将会用到。
有了索引后,我们如何来搜索索引了?一般情况下,我们是通过关键词来检索的,那么如何来组织关键词呢?PostgreSQL 提供了to_tsquery函数来将词组织成tsquery向量,然后通过向量去搜索。如下:SELECT to_tsquery('sql & java'); to_tsquery---------------- 'sql' & 'java'tsquery是一种特殊的数据类型,它会将关键词拼接来表示搜索条件,如&表示搜索的内容必须包含sql和java。举个复杂的例子:SELECT to_tsquery('sql & (java | python)'); to_tsquery------------------------------- 'sql' & ( 'java' | 'python' )这个例子表示,搜索的内容必须包含sql和java与python中的一种。
在开始学习 Java 并发工具之前,大家需要掌握以下技巧:操作系统基本知识,Java 并发编程是基于操作系统基础之上的,了解操作系统基本原理,尤其是操作系统的任务调度管理知识,对理解并发编程工具很有必要。Java 语言基础语法,后继章节中采用 Java 语言做示例。
Java 的日期与时间 API 问题由来已久,Java 8 之前的版本中关于时间、日期及其他时间日期格式化类由于线程安全、重量级、序列化成本高等问题而饱受批评。Java 8 吸收了 Joda-Time 的精华,提供了更优秀易用的 API。关于新的日期时间 API,我们已经在Java日期时间处理这一小节具体介绍。
在上一节我们介绍了通过 Java NIO 可以编写非阻塞式 Socket 程序。Java NIO 新引入的几个类是:ServerSocketChannel、SocketChannel、Selector、SelectionKey、ByteBuffer。其实 Java NIO 既可以编写阻塞式 Socket 程序,也可以编写非阻塞式 Socket 程序。本节将会通过一个简单的 Java TCP 客户端、服务器程序演示 Java NIO 编写 Socket 程序的基本步骤。客户端是通过 Java NIO 阻塞式实现,服务器是通过 Java NIO 非阻塞式实现。
本教程当中使用了一些 Java 项目作为例子,所以需要了解简单的 Java 基础。
我们知道,如果需要运行 Java 程序,必须要安装 JDK,这说明 JDK 中就包含了支持 Java 语言运行的JVM ,我们来看下如何查看本机的 JVM 信息。无论是 Windows 操作系统还是 Linux 操作系统,正确安装 JDK 并且配置好环境变量后,在命令行输入如下命令进行查看:java -version以本人的机器为例,可以看到如下的执行结果:C:\Users\Wayne.WangTJ>java -versionjava version "1.8.0_191"Java(TM) SE Runtime Environment (build 1.8.0_191-b12)Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)我们仔细看下最后一句执行结果,Java HotSpot™ 64-Bit Server VM (build 25.191-b12, mixed mode),这就是我的电脑中 Jvm 虚拟机操作系统的版本。 当然了,安装不同的版本,结果是有所区别的。
这篇文章我们将一起来认识 Kotlin 的函数,Kotlin 中的函数可以说比 Java 中的函数更优,解决 Java 函数调用中存在一些问题。此外还会介绍 Java 中没有的函数,比如顶层函数、中缀函数等等。
我们将在后续详细介绍如何在不同平台上安装 Java,在安装 Java 之前,我们需要理解两个名词,JDK 和 JRE:JRE:Java Runtime Environment (Java 运行时环境)JDK:Java Development Kit (Java 开发工具包)以上两个名词是 Java 平台的两大重要软件,他们分别可以帮助用户运行和开发 Java 程序,JDK 是 JRE 的超集,包含 JRE 的所有内容,以及开发小程序和应用程序所需的工具,例如编译器和调试器。简单来说,我们如果想要利用 Java 语言去开发应用程序,就要在我们的电脑上安装 JDK。本教程使用最新版本的 Java 16。
学习了这么久的 Java,我们对 Java 是纯种的面向对象的编程语言这一概念,可能有了一定的感触,在 Java 中,一切皆是对象。但是随着Python、scala等语言的兴起,函数式编程的概念得到开发者们的推崇,Java 不得不做出调整以支持更广泛的技术要求。在面向函数编程的语言中,Lambda表达式的类型就是函数,但是在 Java 中,Lambda表达式的类型是对象而不是函数,他们必须依赖于一种特别的对象类型——函数式接口。所以说,Java 中的Lambda表达式就是一个函数式接口的对象。我们之前使用匿名实现类表示的对象,都可以使用Lambda表达式来表示。
在大多数人看来,Java 语言已经非常完美,但是,Java 语言并非没有缺陷,Java 语言缺少硬件特定的数据类型,也没有能够指向任意地址的指针或编程方法之类的功能。尽管这些功能有可能被程序员误用或滥用,但不得不承认它们是强大的工具。在本节中,我们对 Java 语言的历史以及主要特性有了一个初步的了解,小伙伴们是不是已经迫不及待,要更加深入了解 Java 了呢?那么在下一小节,我们将了解如何在自己的电脑上安装 Java。
我们创建一个简单的 UDP 服务端程序,代码如下:import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;public class UDPServer { private static final int BIND_PORT = 9002; private static final String BIND_HOST = "127.0.0.1"; private static final int RECV_BUFF_LEN = 1500; private static byte[] inBuff = new byte[RECV_BUFF_LEN]; public static void main(String[] args) { // 构造服务器 Socket,绑定到一个固定的端口,监听的 IP 是 0.0.0.0 try (DatagramSocket udpServer = new DatagramSocket(BIND_PORT)) { // 构造接收消息的数据包,需要传入 byte 数组。 // 我们将这条语句放在循环外,不需要每次消息收发都构造此结构 DatagramPacket inMessage = new DatagramPacket(inBuff, inBuff.length); while (true){ // 接收客户端消息 udpServer.receive(inMessage); System.out.println("Recv UDP message:" + new String(inMessage.getData(), 0, inMessage.getLength()) + " from Client:" + inMessage.getSocketAddress().toString()); String rsp = "Hello Client!"; // 构造发送的消息结构 // 注意!!!对于服务器来说,发送的目标地址一定是接收消息时的源地址,所以从 inMessage 结构获取 DatagramPacket message = new DatagramPacket(rsp.getBytes(), rsp.length(), inMessage.getSocketAddress()); // 发送消息 udpServer.send(message); System.out.println("Send UDP message:" + rsp + " to Client:" + message.getSocketAddress().toString()); // 重置接收数据包消息长度,准备接收下一个消息 inMessage.setLength(inBuff.length); } } catch (IOException e) { e.printStackTrace(); } }}
我们创建一个简单的 UDP 客户端程序,代码如下:import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetSocketAddress;import java.net.SocketAddress;public class UDPClient { private static final int PORT = 9002; private static final String DST_HOST = "127.0.0.1"; private static final int RECV_BUFF_LEN = 1500; private static byte[] inBuff = new byte[RECV_BUFF_LEN]; public static void main(String[] args) { // 创建 UDP 客户端 Socket,选择无参构造方法,由系统分配本地端口号和网络接口 try (DatagramSocket udpClient = new DatagramSocket()){ // 构造发送的目标地址,指定目标 IP 和目标端口号 SocketAddress to = new InetSocketAddress(DST_HOST, PORT); while (true){ String req = "Hello Server!"; // 构造发送数据包,需要传入消息内容和目标地址结构 SocketAddress DatagramPacket message = new DatagramPacket(req.getBytes(), req.length(), to); // 发送消息 udpClient.send(message); System.out.println("Send UDP message:" + req + " to server:" + message.getSocketAddress().toString()); // 构造接收消息的数据包,需要传入 byte 数组 DatagramPacket inMessage = new DatagramPacket(inBuff, inBuff.length); // 接收消息 udpClient.receive(inMessage); System.out.println("Recv UDP message:" + new String(inMessage.getData(), 0, inMessage.getLength()) + " from server:" + inMessage.getSocketAddress().toString()); // 每隔 2 秒发送一次消息 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } catch (IOException e) { e.printStackTrace(); } }}
本教程主要讲解的是 Java 8 新特性中的 Lambda 表达式的语法基础以及应用,所以需要学习本教程的读者至少掌握 Java 基础语法,Java 集合,迭代器,还需要了解部分设计模式以及设计原则为后期部分小节学习做铺垫。
//DCL实现单例模式public class LazySingleTon implements Serializable { //静态成员私有化,注意使用volatile关键字,因为会存在DCL失效的问题 private volatile static LazySingleTon mInstance = null; private LazySingleTon() { //构造器私有化 } //公有获取单例对象的函数 //DCL(Double Check Lock) 既能在需要的时候初始化单例,又能保证线程安全,且单例对象初始化完后,调用getInstance不需要进行同步锁 public static LazySingleTon getInstance() { if (mInstance == null) {//为了防止单例对象初始化完后,调用getInstance再次重复进行同步锁 synchronized (LazySingleTon.class) { if (mInstance == null) { mInstance = new LazySingleTon(); } } } return mInstance; } private Object readResolve() throws ObjectStreamException { return mInstance; }}
本文主要是介绍了 CPU 架构带来的多字节数值在内存中存储时的字节序问题,字节序分为大端序和小端序。在计算机网络中,大端序也叫做网络字节序;相应的主机上的存储顺序叫做主机字节序。在 Java 程序中,由于 Java 程序是在 Java 虚拟机上运行,Java 虚拟机的字节序是大端序。然而 Java 虚拟机运行的 Native 系统的字节序是不确定的,可以通过 java.nio.ByteOrder 的 nativeOrder 方法来确定。对于 Java 网络编程中广泛应用的 ByteBuffer,则默认是大端序,当然你也可以根据需要设置它的字节序。对于多字节数值 Buffer,比如 IntBuffer、LongBuffer,则需要根据他们创建时所依赖的结构,来判定它们的字节序。本节内容相对简单,学习起来也会轻松很多,但是非常重要,需要掌握。
项目中包含一个 cpp 源码文件:native-lib.cppextern "C" JNIEXPORT jstring JNICALLJava_com_imooc_hellojni_MainActivity_stringFromJNI( JNIEnv* env, jobject /* this */) { std::string hello = "This string from C++"; return env->NewStringUTF(hello.c_str());}这个函数的功能很简单,返回一个字串 “This string from C++”。我们看到这个函数的函数名很长:Java_com_imooc_hellojni_MainActivity_stringFromJNI,这是按特定的规范组织的,分解之后各部分的含义如下:Java:表示是给 Java 源码中调用的。com_imooc_hellojni_MainActivity:表示由哪个 Java 类(包名类名)来调用。stringFromJNI:表示本地方法名称,会在 Java 源码中声明。
本章节,我们介绍如何创建我们的 Java 类以及如何运行我们的Java程序,其中 Eclipse 也提供了让我们在运行 Java 程序前设置要传输的参数,在运行设置窗口中其实还有蛮多功能,比如设置 JVM 的参数等,大家熟悉后可以自行尝试。
本章节我们介绍了如何在 Eclipse 中把我们的 Java 程序以 Jar 包的形式导出来,操作上还是非常快捷简单的。当我们的 Java 项目被导出为 Jar文件夹后,其实就可以由此体会 Java 的跨平台特性,因为我们可以在任何安装了 Java 虚拟机的操作系统中运行这个 Java 程序(也就是这个 Jar 包)。
在 Markdown 文件中,在 " 无序列表 -,+,* " 后面使用 「中括号 []」 声明复选框。在中括号中写入 x ,便可实现选中效果。实例 1:#### 复选框 checkbox- [ ] Java- [x] Php或者#### 复选框 checkbox+ [ ] Java+ [x] Php或者#### 复选框 checkbox* [ ] Java* [x] Php这三种语法渲染后的结果相同,渲染结果如下:其转换后的 html 的内容如下:<ul><li class="task-list-item"><input type="checkbox" disabled=""> Java</li><li class="task-list-item"><input type="checkbox" disabled="" checked=""> Php</li></ul>
String[] split(String regex)方法可将字符串切割为子串,其参数regex是一个正则表达式分隔符,返回字符串数组。例如,我们使用空格作为分隔符来切割I love Java字符串,结果将返回含有3个元素的字符串数组:624运行结果:I love Java 注意,有几种特殊的分隔符:* ^ : | . \,要使用转义字符转义。例如:// 以*切割String str2 = "I*love*Java";String[] strArr2 = str2.split("\\*");// 以\切割String str3 = "I\\love\\Java";String[] strArr4 = str3.split("\\\\");// 以|切割String str4 = "I|love|Java";String[] strArr4 = str4.split("\\|");另外,还有一个重载方法String[] split(String regex, int limit),其第二个参数limit用以控制正则匹配被应用的次数,因此会影响结果的长度,此处不再一一举例介绍。