Java基础语法——Java语言介绍

1. Java语言简介

1.1 Java故事

Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。

Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点。Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等。

Java是SUN公司的产品,从1996年发布JDK1.0以来,经过多年的发展陆续发布了JDK1.1,JDK1.2,JDK1.3,JDK1.4,JDK1.5版本。2009年,甲骨文(Oracle)公司宣布收购SUN,甲骨文公司又陆续发布了JDK6.0,JDK7.0,2014年发布了JDK8.0版本。

JAVA是一个小岛产的咖啡的名字,味道独特。SUN公司使用JAVA这个名称寓意着做Java程序就像享受咖啡一样,享受生活。

                                                                图:Java 标志

James Gosling(詹姆斯·高斯林)出生于加拿大,是一位计算机编程天才。在卡内基·梅隆大学攻读计算机博士学位时,他编写了多处理器版本的Unix操作系统,是JAVA编程语言的创始人,被称为Java之父

                                                                图 詹姆斯·高斯林

1.2 Java编程环境

1.2.1 Java开发工具包

JDK(Java Development Kit)称为Java开发包,是一个编写Java应用程序的程序开发环境。JDK是整个Java的核心,包括了Java运行环境(Java Runtime Envirnment),一些Java工具和Java的核心类库(Java API)。可以把Java API类库中的Java SE API子集和Java虚拟机这两部分统称为JRE(JAVA Runtime Environment),JRE是支持Java程序运行的标准环境。

1.2.2 Java运行时环境

JRE是个运行环境,JDK是个开发环境。因此写Java程序的时候需要JDK,而运行Java程序的时候就需要JRE。而JDK里面已经包含了JRE,因此只要安装了JDK,就可以编辑Java程序,也可以正常运行Java程序。

1.2.3 Java 虚拟机

JVM是Java Virtual Machine(Java虚拟机)的缩写。JVM是java的核心和基础,是java编译器和OS平台之间的虚拟处理器,主要用于实现Java跨平台。

下图是Java平台的结构图,观察下图会发现JDK包含着JRE,JRE包含着JVM。

                                                                图 Java平台结构

JDK、JRE、JVM的简化图如下:

                                                        图 JDK、JRE、JVM的关系

1.3 Java编程工具

  • Eclipse:一个开放源代码的、基于Java的可扩展开发平台。

  • NetBeans:开放源码的Java集成开发环境,适用于各种客户机和Web应用。

  • +IntelliJ IDEA:在代码自动提示、代码分析等方面的具有很好的功能。

  • MyEclipse:由Genuitec公司开发的一款商业化软件,是应用比较广泛的Java应用程序集成开发环境。

  • EditPlus:如果正确配置Java的编译器“Javac”以及解释器“Java”后,可直接使用EditPlus编译执行Java程序。

1.4 Java技术应用

1、Android应用

许多的 Android应用都是Java程序员开发者开发。虽然 Android运用了不同的JVM以及不同的封装方式,但是代码还是用Java语言所编写。相当一部分的手机中都支持JAVA游戏,这就使很多非编程人员都认识了JAVA。

2、在金融业应用的服务器程序

Java在金融服务业的应用非常广泛,很多第三方交易系统、银行、金融机构都选择用Java开发,因为相对而言,Java较安全。大型跨国投资银行用Java来编写前台和后台的电子交易系统,结算和确认系统,数据处理项目以及其他项目。大多数情况下,Java被用在服务器端开发,但多数没有任何前端,它们通常是从一个服务器(上一级)接收数据,处理后发向另一个处理系统(下一级处理)。

3、网站

Java 在电子商务领域以及网站开发领域占据了一定的席位。开发人员可以运用许多不同的框架来创建web项目,SpringMVC,Struts2.0以及frameworks。即使是简单的 servlet,jsp和以struts为基础的网站在政府项目中也经常被用到。例如医疗救护、保险、教育、国防以及其他的不同部门网站都是以Java为基础来开发的。

4、嵌入式领域

Java在嵌入式领域发展空间很大。在这个平台上,只需130KB就能够使用Java技术(在智能卡或者传感器上)。

5、大数据技术

Hadoop以及其他大数据处理技术很多都是用Java,例如Apache的基于Java的HBase和Accumulo以及 ElasticSearchas。

6、高频交易的空间

Java平台提高了这个平台的特性和即时编译,他同时也能够像 C++ 一样传递数据。正是由于这个原因,Java成为的程序员编写交易平台的语言,因为虽然性能不比C++,但开发人员可以避开安全性,可移植性和可维护性等问题。

7、科学应用

Java在科学应用中是很好选择,包括自然语言处理。最主要的原因是因为Java比C++或者其他语言相对其安全性、便携性、可维护性以及其他高级语言的并发性更好。

1.5 Java平台的版本

Java不只是语言,Java是一个平台,Java平台有三个版本,分别是JavaSE、JavaEE、JavaME。

Java SE(Java Platform,Standard Edition)。Java SE 以前称为 J2SE。它允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的 Java 应用程序。Java SE 包含了支持 Java Web 服务开发的类,并为 Java Platform,Enterprise Edition(Java EE)提供基础。

Java EE(Java Platform,Enterprise Edition)。这个版本以前称为 J2EE。企业版本帮助开发和部署可移植、健壮、可伸缩且安全的服务器端 Java 应用程序。Java EE 是在 Java SE 的基础上构建的,它提供 Web 服务、组件模型、管理和通信 API,可以用来实现企业级的面向服务体系结构(service-oriented architecture,SOA)和 Web 2.0 应用程序。

Java ME(Java Platform,Micro Edition)。这个版本以前称为 J2ME。Java ME 为在移动设备和嵌入式设备(比如手机、PDA、电视机顶盒和打印机)上运行的应用程序提供一个健壮且灵活的环境。Java ME 包括灵活的用户界面、健壮的安全模型、许多内置的网络协议以及对可以动态下载的连网和离线应用程序的丰富支持。基于 Java ME 规范的应用程序只需编写一次,就可以用于许多设备,而且可以利用每个设备的本机功能。

2. 开发前准备

2.1 下载和安装JDK

在开发一个Java应用程序前,首先要确保计算机上安装有JDK,JDK可以从Oracle公司的网站上(Java Downloads | Oracle)获取。由于Java是跨平台的,因此要选择相应平台下的JDK进行下载。本书以windows平台为例进行讲解,因此需要下载windows平台下的JDK。

                                                          图 Oracle公司JDK下载网页

JDK(Java Development Kit),即Java开发工具包,是Oracle公司提供的用于开发Java应用程序的标准开发工具包。一台电脑要想运行Java程序,必须安装JDK。JDK中包含JRE(Java Runtime Environment),JRE是Java运行时环境。JRE中包含了JVM(Java Virtual Machine)即Java虚拟机和JCL(Java Class Library)即Java类库。

从官方下载JDK后进行安装,默认安装到C:\Program Files\Java\jdk1.8.0_121目录下。JDK的目录中包含两个重要目录,它们是bin目录和lib目录。bin目录中存放JDK的命令,lib目录存放系统类库。

                                                        图 JDK安装后的目录截图

 2.2 配置JDK的环境变量

JDK安装后要对JDK进行环境变量配置,环境变量需要配置3个属性,如下表:

变量名变量值
JAVA_HOMEJDK的安装根目录
CLASSPATHJAVA_HOME下lib目录中的所有jar文件和当前目录
PATHJAVA_HOME下bin目录中所有的文件

假设JDK的安装目录为C:\Program Files\Java\jdk1.8.0_121,环境变量配置如下:

变量名变量值
JAVA_HOMEC:\Program Files\Java\jdk1.8.0_121
CLASSPATH%JAVA_HOME%\lib;.
PATH%JAVA_HOME%\bin

具体的配置步骤如下:

  1. 右击我的电脑,选择“属性”菜单,找到“高级系统设置”选项。

                                                                图 配置环境变量

  1. 在点击“高级系统设置”弹出的对话框中选择“高级”选项卡,在高级选项卡中选择“环境变量”。

图 配置环境变量

  1. 在点击“环境变量”弹出的对话框中点击系统变量下的“新建”。在新建对话框中输入变量名“JAVA_HOME”,变量值是JDK安装的根目录,例如“C:\Program Files\Java\jdk1.8.0_121”

                                                                图 配置环境变量

  1. 同样的方法创建CLASSPATH环境变量和修改系统的PATH变量。

                                                                图 配置环境变量

                                                                图 配置环境变量

配置环境变量后,可以通过控制台测试配置是否正确。打开控制台,输入java命令回车后提示如下图所示内容即配置成功。

                                                        图 检查环境配置是否成功

2.3 编写HelloWorld程序 

2.3.1 第一个示例程序HelloWorld

安装JDK并配置好环境变量后就可以进行java编程了,下面编写一个入门级别的Java程序来体验Java开发的神奇之旅。开发一个Java程序分3步,如下:

  1. 创建Java源程序。

  2. 将源程序编译为字节码文件。

  3. 执行字节码文件。

任务1:使用Java语言编写HelloWorld程序
该任务是使用Java语言编写一个程序,实现在控制台显示“HelloWorld”的功能。该任务的目的是掌握开发Java的步骤,无需关注程序细节。

第一步:创建Java源程文件

Java源文件是以.java结尾的文本文件,是程序员创建和编写的。

在C盘根目录下创建一个目录,命名为java,在c:\java目录中新建一个记事本文件,将该文件命名为HelloWorld.java。在HelloWorld.java文件中输入下面的代码。

代码示例

/**                       
*   HelloWorld程序 
**/                      
public class HelloWorld{    
/**
*main方法是程序的入口点  
**/ 
    public static void main(String[] args){     
        System.out.println("HelloWorld");   
    }
}
 

带你分析代码:

  1. 上面的代码创建了一个类,类名是HelloWorld,类名必须和文件名一致。

  2. HelloWorld类中定义了一个方法,方法名称叫main,Java程序是从main方法开始运行的。

  3. main方法向控制台输出"HelloWorld"字符串。

  4. 注意Java语言是区分大小写的。

第二步:将源文件编译为字节码文件

字节码文件是以.class结尾的文件,字节码文件通过Javac编译器编译出来的。

打开控制台,在控制台中使用Java编译器命令(javac)将java源文件编译成字节码文件,字节码文件是以.class为扩展名的文件。编译后会在C盘根目录下产生编译完的HelloWorld.class字节码文件,字节码文件是不允许修改的,只能修改源文件后重新生成字节码文件。

                                                                图 编译java源文件

第三步:运行字节码文件

在控制台中使用java解释器命令(java)运行HelloWorld字节码文件,显示java程序运行结果。

                                                                图 运行字节码文件

HelloWorld这个程序几乎是每一门编程语言中的第一个示例程序。那么,这个著名的程序究竟从何而来呢?隐含着哪些历史背景呢?可从度娘中了解相关的信息。

2.3.2 Java的注释

Java的注释分为三种,分别是单行注释、多行注释、文档注释。

单行注释:// 注释的内容

多行注释:/* 注释的内容 /

文档注释:/** 注释的内容 */

例如:

/** 
* 我是文档注释,我用于生产注释的文档 
* */
public static void main(String[] args) {
/*
*我是多行注释,当注释内容用一行描述不完时应该使用我。  
*/
//我是单行注释,当注释内容用一行可以描述完成时,应该使用我  
System.out.println("Hello World"); 
}

2.4 Java跨平台特性与JVM

2.4.1 Java跨平台

完成了HelloWorld程序后,我们以HelloWorld程序为例,分析Java程序执行过程和Java跨平台的特性。

Java是跨平台的语言,平台是指操作系统和CPU,每个平台能够运行与该平台匹配的机器码。Java跨平台就是让所有的平台都能运行Java代码。Java做到了write once, run anyWhere,一次编写到处运行。Java是如何做到的呢?Java是通过JVM(Java Virtual Machine),即Java虚拟机来实现的。

如下图,所有的Java源程序(Source.java)都可以编译成字节码(Source.class),字节码可以执行在任何一个JVM上,JVM可以运行在专用的平台上,例如JVM for DOS,JVM for windows,JVM for Unix等。所有的JVM都可以将字节码文件(Source.class)转换成平台对应的机器码,如下图所示:

                                                            图 工作原理和跨平台

回顾Java程序执行的3个步骤。即从Java源文件到字节码文件到执行。Java程序的执行过程是首先通过java编译器命令javac,将Java源程序编译成字节码文件,字节码文件在虚拟机中使用java解释器命令java,将字节码文件转换成机器码,机器码运行在各自的平台上,以此实现java跨平台。

跨平台是Java最显著的特性,Java还有一些其他特性。例如:简单性,面向对象,分布性,编译和解释性,稳健性,安全性,可移植性,高性能,多线程性,动态性等,这些特性需要在后续的学习中体会。

2.4.2 编译和解释

上述中提到了编译和解释,编译和解释是计算机语言运行的两种方式,有些语言是编译执行的,有些语言是解释执行的。它们的区别如下:

  1. 编译执行是一次性把源程序编译成计算机能识别的目标程序,因此计算机执行起来速度非常快,但是编译后的目标程序只能在同一平台下运行。比如用C语言编写的程序,在Windows平台下编译的结果,离开Windows平台将无法正确的运行。

  2. 解释执行的程序是指解释器将源程序逐句翻译的同时逐句执行,因此执行起来速度上不占优势,但是这种程序执行时往往不依赖于特定的平台,通过在不同平台上提供不同的解释器就可以跨平台执行。

  3. Java源程序到字节码是编译执行的,字节码到机器码是解释执行。

问:大佬,Java这个名称是怎么来的呢?
答:Java是印度尼西亚爪哇岛的英文名称,因盛产咖啡而闻名。Java语言中的许多库类名称,多与咖啡有关:如JavaBeans(咖啡豆)、NetBeans(网络豆)以及Object Beans(对象豆)等等。SUN和JAVA的标识也正是一杯正冒着热气的咖啡。

2.5 IntelliJ Idea集成开发工具安装与使用

下载地址Download IntelliJ IDEA: The Capable & Ergonomic Java IDE by JetBrains

3. Java的变量与表达式

3.1 数据类型与变量

3.1.1 数据类型

数据是描述客观事物的数字、字母以及能够输入到计算机中的符号。例如“武松”、“软件一班”、28、170等都是数据。数据可根据其特点进行分类,例如“武松”和“软件一班”可以归为字符串类,28和170可归为数字类。

在Java中数据类型分为两大类:基本数据类型和引用数据类型。基本类型包括八种,分别是byte,short,int,long,float,double,boolean,char,引用类型包括数组、接口、类等,除了基本类型以外的数据都是引用类型。

数据类型占用空间保存范围使用举例
boolean布尔型1字节true或false保存性别、婚否
byte字节型1字节-128~127对字节操作时使用,如文件读写
char字符型2字节0~65535保存单个字母或汉字时使用
short短整型2字节-32768~32767保存较小的整数时使用
int整型4字节-2147483648~2147483647保存一般的整数时使用
long长整型8字节-9223372036854775808~9223372036854775807保存较长的整数时使用
float浮点型(单精度)4字节-3.403e38~3.403e38保存小数时使用
double浮点型(双精度)8字节-1.798e308~1.798e308保存精度较高的小数时使用

表 八种基本数据类型

基本数据类型范围说明

//byte
System.out.println("最小值:Byte.MIN_Value = "+ Byte.MIN_VALUE);
System.out.println("最大值:Byte.MAX_Value = "+ Byte.MAX_VALUE);
System.out.println();
​
//short
System.out.println("最小值:Short.MIN_Value = "+ Short.MIN_VALUE);
System.out.println("最大值:Short.MAX_Value = "+ Short.MAX_VALUE);
System.out.println();
​
//int
System.out.println("最小值:Integer.MIN_Value = "+ Integer.MIN_VALUE);
System.out.println("最大值:Integer.MAX_Value = "+ Integer.MAX_VALUE);
System.out.println();
​
//long
System.out.println("最小值:Long.MIN_Value = "+ Long.MIN_VALUE);
System.out.println("最大值:Long.MAX_Value = "+ Long.MAX_VALUE);
System.out.println();
​
//float
System.out.println("最小值:Float.MIN_Value = "+ Float.MIN_VALUE);
System.out.println("最大值:Float.MAX_Value = "+ Float.MAX_VALUE);
System.out.println();
​
//double
System.out.println("最小值:Double.MIN_Value = "+ Double.MIN_VALUE);
System.out.println("最大值:Double.MAX_Value = "+ Double.MAX_VALUE);
System.out.println();
​
//char
System.out.println("最小值:Character.MIN_Value = "+ Character.MIN_VALUE);
System.out.println("最大值:Character.MAX_Value = "+ Character.MAX_VALUE);
System.out.println();

3.1.2 变量

变量是指在程序运行过程中其值可以改变的量。变量的使用必须先声明,然后初始化,最后才能使用变量。

变量的声明语法:

[修饰符] 数据类型 变量名称[=值];

例如

int age = 28;
​
int age;
​
int age,score;
​
float f=1.2F;
​
double d=2.0D;
​
long L= 38L;

讲:变量就是计算机内存中存放数据的单元,定义变量的本质就是分配内存。当把数值赋给变量时,实际上就是将数值存储到变量占用的内存单元中。

3.1.3 变量命名规则

Java语言是区分大小写的,变量的命名也有规范,如下表

规则正确示例错误示例
变量名不能以数字开头a33a
除了“_”或“$”符号外,变量名中不能包含其他标点符号或运算符my$It%it
变量名不能使用Java语言中的关键字longerlong, void, class

表 变量命名规则

每个公司在开发中都有自己定义变量的规范,无论各公司规范是否相同,都会遵循“见名知义”的原则。

问:变量的名称在命名上有什么规则吗?
答:变量命名常用的方法有帕斯卡命名法和骆驼命名法,帕斯卡命名法是指一个变量由多个单词构成时,每个单词首字母都大写,例如GetUserName。骆驼命名法是指一个变量由多个单词构成时,第一个单词首字母小写,其余单词首字母都大写,例如:getUserName

3.2 表达式和运算符

对数据进行加工和处理称为运算,表示各种运算的符号称为运算符,参与运算的数据称为操作数。

3.2.1 表达式

表达式是运算符和操作数的有效组合,操作数可以是变量、常量、方法调用的返回值。例如表达式 z = x + y中z、x、y是操作数,=、+是运算符。

                                                                图 运算符和操作数

3.2.2 运算符

3.2.2.1 算术运算符

算术运算符用来完成数学上的加、减、乘、除四则运算。

运算符示例说明
+3+2加法运算符,求两个操作数的和。
-3-2减法运算符,求两个操作数的差。
*3*2乘法运算符,求两个操作数的积。
/3/2除法运算符,求两个操作数的商。
%3%2求余运算符,求两个整数的余数。
++int a = 3;++a 或者 a++自增运算符,a++相当于 a = a+1。
--int a=3;--a 或者 a--自减运算符,a--相当于 a = a-1。

                                                                    表 算术运算符

任务1:求矩形的周长
该任务根据给定的宽和高求出矩形的周长

代码示例

public class Task1 {    
    public static void main(String[] args) {        
        int width = 30;     
        double height = 10.5;       
        double result = (width + height) * 2;       
        System.out.print("矩形的周长是:"+result); 
    }
}
带你分析代码:
1. 程序中定义了int类型的变量width,初始化为30,定义了double类型的变量height,初始化为10.5,定义了表达式(width+height) * 2,并将表达式的结果赋值给double类型的变量result,最后向控制台输出矩形的周长。

运行结果:矩形的周长是:81.0

任务2:求三角形面积
该任务根据给定的宽和高求出三角形的面积。

代码示例

public class Task2 {    
    public static void main(String[] args) {        
        int width = 30;     
        int height = 10;        
        double result = width * height / 2;     
        System.out.print("三角形的面积是:"+result);    
    }
}

带你分析代码:

1. 程序中定义了int类型的变量width,初始化为30,定义了int类型的变量height,初始化为10,定义了表达式width*height/2,并将表达式的结果赋值给double类型的变量result,最后向控制台输出三角形的面积。
任务3:剖析自增和自减
该任务剖析自增和自减运算在赋值运算中的执行顺序。

代码示例

public class Task3 {    
    public static void main(String[] args) {        
        int i= 5,x;     
        x=i++;      
        System.out.println("x="+x);     
        System.out.println("i="+i);             
        x=++i;      
        System.out.println("x="+x);     
        System.out.println("i="+i); 
    }
}

带你分析代码:

1. 程序中定义了int类型的变量i,初始化为5,定义了int类型的变量x。定义了表达式x=i++,在该表达式中有两个运算,一是赋值运算,二是自增运算,由于++写在变量i的后面,因此++运算要后于赋值运算。即先将i的值赋给x后,i再自增。运行的结果是x的值是5,i的值是6.
2. 程序中定义了表达式x=++i,在该表达式中有两个运算,一是赋值运算,二是自增运算,由于++写在变量i的前面,因此++运算要先于赋值运算。即先将i的值自增,然后再将自增后的i的值赋给x。运行的结果是x的值是7,i的值是7。

运行结果:

x = 5
i = 6
x = 7
i = 7

3.2.2.2 关系运算符

关系运算符用于操作数之间的比较。

运算符示例说明
>a>b如果a>b成立,结果为true,否则结果为false
>=a>=b如果a>=b成立,结果为true,否则结果为false
<a<b如果a<b成立,结果为true,否则结果为false
<=a<=b如果a<=b成立,结果为true,否则结果为false
==a==b如果==>b成立,结果为true,否则结果为false
!=a!=b如果a!=b成立,结果为true,否则结果为false

表 关系运算符

注意:该表中运算符只能和两个操作数进行比较

3.2.2.3 逻辑运算符

逻辑运算符是对布尔类型的操作数进行与、或、非的运算。

运算符示例说明
&&a>b && a>ca大于b,并且a大于c
||a>b || a>ca大于b,或者a大于c
!(a>b)a大于b不成立

表 逻辑运算符

int a = 10;
        int b = 5;
        int c= 8;
        System.out.println(a < b && b < c);
        //短路与,左边为false,右边不执行
        System.out.println(a < b || b < c);
        //短路或,左边为true,右边不执行

3.2.2.4 位运算

  1. 数学中的二进制

先简单介绍下二进制,二进制是用0和1两个数码表示的数字,进位规则是“逢二进一”,借位规则是“借一当二”。程序员都知道,二进制在当代计算机中非常微小的开关,用”开(true)“表示1,”关(false)“表示0。二进制数据采用的位置计数法,其权位是以 2 为底的幂。

1.1 二进制转十进制 例1:二进制数 1101 与十进制转换: (1 x 2³) + (1 x 2²) + (0 x 2¹) + (1 x 2⁰) = 8 + 4 + 0 + 1 = 13 例2:二进制数 111.01 与十进制转换: (1 x 2²) + (1 x 2¹) + (1 x 2⁰) + (0 x 2⁻¹) + (1 x 2⁻²) = 4 + 2 + 1 + 0 + 0.25 = 7.25

浮点型的二进制数在Java中用的不多,后面就暂且不论

1.2 十进制转二进制 除以2取余,逆序排列 (除二取余法) 例:89 = 1011001

十进制数/2商(下次的被除数)余数(二进制数)
89 / 2441
44 / 2220
22 / 2110
11 / 251
5 / 221
2 / 210
1 / 201

以上表格中的余数倒过来,就是 89 对应的二进制数

  1. JAVA 中的二进制 2.1 二进制转十进制 Java 中的二进制数是以 0b + 数字形式,b 大小写不限制,例如:0b101 表示二级制数 101,可以直接赋值到 十进制的 int 基本数据类型。常见表示方法有 int binary = 0b101;

    int binary = 0b101;
    System.out.println("0b101 =" + binary);
    //输出是:0b101 = 5

    2.2 十进制转二进制

    通过 Integer 的整型包装类中的方法 toBinaryString 可以把十进制转换成二进制然后通过字符串输出。

    int i =5;
    String binary = Integer.toBinaryString(i);
    System.out.println(i + " = " + binary);
    //输出是:5 = 101

  2. 位运算符 位运算符用来对二进制位进行操作,Java 中提供了如下表所示的位运算符:位运算符中,除 ~ 以外,其余均为二元运算符。

运算符描述
&与,两个二进制数如果相对应位都是1,则结果为1,否则为0
|或,两个二进制数如果相对应位都是0,则结果为0,否则为1。
^异或,如果相对应位值相同,则结果为0,否则为1
~非(取反),按位取反运算符翻转操作数的每一位,即0变成1,1变成0。 一元运算符
<<按位左移,左操作数按位左移右操作数指定的位数。
>>按位右移,左操作数按位右移右操作数指定的位数。
>>>无符号按位右移,左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。

在计算机中位运算符比数学中常规的加减乘除效率高很多,对于一些追求效率的数据结构或者算法来说,掌握位运算符的用法会让程序员在开发过程中如虎添翼,但是目前来看用的真的不是很多,可能和可读性不高有关吧。总之希望通过学习能对位运算符能有所了解,更能实际运用到自己的项目或者工作中去。

Java定义了位运算符,应用于整数类型(int),长整型(long),短整型(short),字符型(char),和字节型(byte)等类型。位运算符作用在所有的位上,并按位运算。假设a = 60,b = 13; 我们来看看各种位运算之后的运算结果。

3.1 & 与运算 &(与),两个二进制数如果相对应位都是1,则结果为1,否则为0。例如:60 & 13 = 12 60 的二进制数是 111100,13的二进制数是 1101 以32位bit位计算,剩余位数补0,对于每个位上的操作,进行And比较,如果都是1则结果的相应位也是1,否则是0。 图示如下:

//Java代码
int a = 60;
int b = 13;
System.out.println(Integer.toBinaryString(a));
System.out.println(Integer.toBinaryString(b));
System.out.println("60 & 13 = " + (a & b));

实际应用:判断奇偶数 判断奇偶数:假如存在 a & 1 结果为 0 ,a 就是偶数。a & 1结果为 1 ,a 就是奇数。 我们知道,二进制数有 逢二进一 的规则,那么凡是偶数,第一位必然是 0 ,奇数第一位必然是 1。通过例子我们也知道 & 运算是两个二进制数的运算,相应位都是1则结果的相应位也是1,对于1来说,第一位是1,其它位都是0。那么任何二进制奇数 & 1,只有第一位满足都是1,所以第一位是1,其它位都是0。如果该二进制数为偶数,如果该二进制数是偶数,则第一位是0,所以 & 1 后,所有位都为 0,我们看下下图就一目了然:

//java代码
int a = 60;
int b = 13;
System.out.println("60 & 1 = "+ (a & 1));
System.out.println("13 & 1 = "+ (13 & 1));
​
//输出结果如下:
60 & 1 = 0 //偶数
13 & 1 = 1  //奇数 

   

3.2 | 或运算 |(或),两个二进制数如果相对应位都是0,则结果为0,否则为1。其实很好理解,或运算正好对与运算,和我们的逻辑运算符 && 和 || 非常像,我们想象 1 = true,0 = false 。 对于与运算符,需要都为true则true,对于或运算符,只要1个为true则true。图示如下:

//java代码
int a = 60;
int b = 13;
System.out.println(Integer.toBinaryString(a));
System.out.println(Integer.toBinaryString(b));
System.out.println("二进制 60 | 13 = " + Integer.toBinaryString(a | b));
System.out.println("60 | 13 =" + (a | b));

3.3 ^ 异或运算符

^(异或),如果相对应位值相同,则结果为0,否则为1。这次和前面不同了,相当于逻辑运算符中的 == 和 != 区别是异或运算 == 的话是false ,!= 的话是true,继续撕图:

//java代码
int a = 60;
int b = 13;
System.out.println(Integer.toBinaryString(a));
System.out.println(Integer.toBinaryString(b));
System.out.println("二进制 60 ^ 13 = " + Integer.toBinaryString(a ^ b));
System.out.println("60 ^ 13 =" + (a ^ b));

实际应用:Swap 两数互换 异或运算符用于 Swap 互换不需要第三个temp变量,我们可以把异或想象成减法取绝对值, 在二进制中,由于逢二进一,所以有1 - 1 = 0, 1 - 0 = 1, 0 - 0 = 0这样的特性,所以这三个等式中,任意两个数相减的绝对值都等于第三个数,用这种特性,就能进行Swap的两数互换。

// java 代码
int a = 60;
int b = 13;
//1.异或运算	
	a ^= b;//a = 49
	b ^= a;//b = 60
	a ^= b;//c = 13

//2.引入中间变量
int tmp = a;//tmp = 60
  	a = b;//a = 13
    b = tmp; //b = 60

//3.加减法       
    a = a + b;//73
    b = a - b;//60
    a = a - b;//13

3.4 ~ 非(取反)运算

~(非),按位取反运算符翻转操作数的每一位,即0变成1,1变成0。所有的位运算符中,只有 ~ 运算符是一元运算符。如果我们把 1 看做 true 0 看做 false,取反操作就等于是每一位进行 !操作,!0 或者 !1,看下图。

// java代码
int a = 60;
int b = 13;
System.out.println("二进制 a = "+Integer.toBinaryString(a));
System.out.println("二进制 ~60 = "+Integer.toBinaryString(~a));
System.out.println("十进制 ~60 = "+~a);
```
int a = 60;
int b = 13;
System.out.println("二进制 a = "+Integer.toBinaryString(a));
System.out.println("二进制 ~60 = "+Integer.toBinaryString(~a));
System.out.println("十进制 ~60 = "+~a);

3.5 <<按位左移

按位左移,左操作数按位左移右操作数指定的位数。 写作 a << n ,使 a 的二进制数整体向左移动 n 位,并在低位补0。这个操作等同于 a x (2n) ,看图说话:

//java代码
int a = 60;
System.out.println("十进制 a = "+a);
System.out.println("二进制 a = "+Integer.toBinaryString(a));
System.out.println("二进制 a<<2 = "+Integer.toBinaryString(a << 2));
System.out.println("十进制 a<<2 = "+(a <<2));

3.6 >> 按位右移

按位右移,左操作数按位右移右操作数指定的位数。写作 a >> n ,使 a 的二进制数整体向右移动 n 位。这个操作等同于 a / (2n) , 如图:

//java代码
int a = 60;
System.out.println("十进制 a = "+a);
System.out.println("二进制 a = "+Integer.toBinaryString(a));
System.out.println("二进制 a>>2 = "+Integer.toBinaryString(a >> 2));
System.out.println("十进制 a>>2 = "+(a >>2));

3.7 >>> 无符号按位右移

按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。使 a 的二进制数整体向右移动 n 位,并在高位补0。这个操作等同于 a / (2n),他和 >> 区别在于高位补0,所以也叫无符号右移。如下图:

//java代码
int a = 60;
System.out.println("十进制 a = "+a);
System.out.println("二进制 a = "+Integer.toBinaryString(a));
System.out.println("二进制 a>>>2 = "+Integer.toBinaryString(a >>> 2));
System.out.println("十进制 a>>>2 = "+(a >>>2));

经过大量实验,在 Java 中其实位运算主要还是用在对位操作有要求的场景,在大多数情况下,位和数学运算的效率差不多。所以不需要为了装B而用位运算,这样会导致效率没怎么提升,代码阅读性还降低了。

3.2.2.5 算术复合运算符

算术复合运算符是多个算术运算同时进行的计算。包括+=、-=、*=、/=、%=。

表达式等价的Java代码运行的结果
a += 3a = a + 3a的结果是 13
a -= 3a = a - 3a的结果是 7
a *= 3a = a * 3a的结果是 30
a /= 3a = a / 3a的结果是 3
a %= 3a = a % 3a 的结果是 1

                                                                表 复合赋值运算

3.2.2.6 运算符的优先级

当表达式中有多个运算符参与运算时,必须为每种运算符规定一个优先级,以决定运算符在表达式中的运算次序。优先级高的先运算,优先级低的后运算,优先级相同的由结合性确定计算次序。运算符的优先级及结合性如下表所示。

运算符优先级结合性
[ ]1从左向右
! ~ ++ -- +(一元运算) -(一元运算)2从右向左
* / %3从左向右
+ -4从左向右
<< >> >>>5从左向右
< <= > >= instanceof6从左向右
== !=7从左向右
&8从左向右
^9从左向右
|10从左向右
&&11从左向右
||12从左向右
?:13从右向左
= += -= *= /= %= &= |= ^= <<= >>= >>=14从右向左

                                                        表 运算符的优先级

任务4:新生老成绩大比拼
该任务是从键盘上输入新生和老生的java成绩和数据库成绩,然后比较成绩。
该任务涉及了如何从键盘上输入数据。Java在JDK中提供了很多已经开发好的类库,在程序开发过程中可以直接使用。java.util.Scanner类提供了获取用户在控制台中输入的数据的功能。使用时分两步:
1、 创建Scanner对象,该对象用于接收用户在控制台中输入的数据。java.util.Scanner input=new java.util.Scanner(System.in);
2、 使用Scanner对象提供的方法获取用户输入的数据:int score = input.nextInt();

代码示例

public class Task4 {    
    public static void main(String[] args) {        
        Scanner input =new Scanner(System.in);      
        int xb_java;        
        int xb_sql;     
        int lb_java;        
        int lb_sql;     
        System.out.println("请输入新生的java成绩");     
        xb_java = input.nextInt();      
        System.out.println("请输入新生的sql成绩");      
        xb_sql = input.nextInt();       
        System.out.println("请输入老生的java成绩");     
        lb_java = input.nextInt();      
        System.out.println("请输入老生的sql成绩");      
        lb_sql = input.nextInt();       
        System.out.println("新生java成绩追上老生了吗?"+(xb_java > lb_java));
        System.out.println("新生sql成绩追上老生了吗?"+(xb_sql > lb_sql));
        System.out.println("新生每门课成绩都追上老生了吗?"+((xb_sql > lb_ sql) && (xb_java > lb_java)));  
    }
}

运行结果:

请输入新生的java成绩
78
请输入新生的sql成绩
89
请输入老生的java成绩
83
请输入老生的sql成绩
92
新生java成绩追上老生了吗?
false
新生sql成绩追上老生了吗?
false
新生每门课成绩都追上老生了吗?
false

Scanner对象中提供了多种方法用于输入不同类型的数据,如下表:

方法作用
next输入字符串
nextInt输入int类型整数
nextShort输入short类型整数
nextLong输入long类型整数
nextFloat输入float类型浮点数
nextDouble输入double类型浮点数
nextByte输入byte类型数据

                                                        表 Scanner类输入数据的方法

3.3 数据类型转换

当将一种数据类型的值赋给另一种数据类型的变量时,出现了数据类型的转换。在整数类型和浮点数类型中,可以将数据类型按照精度从“高”到“低”排列如下级别:

double  float  long  int  short  byte

高级别 -------------------------------------->低级别

3.3.1 自动转换与强制转换

赋值运算中,数据类型转换规则如下:

1:当将低级别的值赋给高级别的变量时,系统会自动完成数据类型的转换。例如:

int i = 52;

float x;

x = i; //自动转换

2:当将高级别的值赋给低级别的变量时,必须进行强制类型转换。强制类型转换的形式如下:

(类型标识符)待转换的值;

例如:

float f = 1.6F;

int i=(int)f; //将float类型的值转换成int类型的值后存储到int类型变量i中。

强制类型转换可能会造成数据丢失,如上例中f的值是1.6,转换成int类型后会丢失精度,i的值是1。

任务5:整数相除
该任务通过整数相除研究数据类型转换。

代码示例

public class Task5 {    
    public static void main(String[] args) {        
        int i=15,j=4,k;     
        float f1,f2;        
        k=i/j;      
        f1=i/j;     
        f2=(float)i/j;
        System.out.println("k="+k);     
        System.out.println("f1="+f1);       
        System.out.println("f2="+f2);   
    }
}

带你分析代码:

1. 程序中声明了3个int类型的变量i、j、k。并给i和j分别初始化为15和4,还声明了两个float类型的变量f1和f2。在“k=i/j”中,int类型值15与4进行整除运算,其结果是int类型值3,并将该值赋值给int类型变量k,所以k的值是3。通过“f1=i/j”,int类型值15与4进行整除运算,其结果是int类型值3,在将该值赋给float类型变量f1时,系统自动进行数据类型转换,将int类型值3转换成float类型值3.0,并将转换后的值赋给f1,所以f1的值是3.0。在“f2=(float)i/j”中,int类型值15被强制转换成float类型值15.0,该值与int类型值4进行除法运算时,系统自动将int类型值4转换成float类型值4.0,然后对15.0与4.0进行除法运算,其结果是float类型值3.75,最后将该值赋给float类型变量f2,所以f2的值是3.75。

运行结果:

k=3
f1=3.0
f2=3.75

3.3.2 表达式的数据类型

表达式的数据类型由运算结果的数据类型决定。例如:

public class Example1 { 
    public static void main(String[] args) {        
        int i= 5;       
        float f= 6f;        
        double d = 7.8d;
        double result =  i + f + d;
    }
}
​

表达式result = i + f + d中的操作数i是int类型,f是float类型,d是double类型,计算的结果result的类型是表达式中占用字节空间最大的类型,即double类型。

4. 课后练习

  1. 请描述变量声明规则与规范。

    答:

    1.所有编程相关的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。反例:_name / __name / $Object / name_ / name$ / Object$
    2.【强制】所有编程相关的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义。注意,即使纯拼音命名方式也要避免采用。正例:ali / alibaba / taobao / kaikeba / aliyun / youku / hangzhou 等国际通用的名称,可视同英文。反例:DaZhePromotion【打折】/ getPingfenByName()【评分】 / String fw【福娃】/ int 变量名 = 3
    3.【强制】代码和注释中都要避免使用任何人类语言中的种族歧视性或侮辱性词语。正例:blockList / allowList / secondary反例:blackList / whiteList / slave / SB / WTF
    4.【强制】类名使用 UpperCamelCase 风格,以下情形例外:DO / PO / DTO / BO / VO / UID 等。正例:ForceCode / UserDO / HtmlDTO / XmlService / TcpUdpDeal / TaPromotion反例:forcecode / UserDo / HTMLDto / XMLService / TCPUDPDeal / TAPromotion
    5.【强制】方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格。正例:localValue / getHttpMessage() / inputUserId
    6.【强制】常量命名应该全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。正例:MAX_STOCK_COUNT / CACHE_EXPIRED_TIME反例:MAX_COUNT / EXPIRED_TIME
    7.【强制】抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾,测试类命名以它要测试的类的名称开始,以 Test 结尾。
    8.【强制】类型与中括号紧挨相连来定义数组。正例:定义整形数组 int[] arrayDemo。反例:在 main 参数中,使用 String args[] 来定义。
    9.【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形 式,但是类名如果有复数含义,类名可以使用复数形式
  2. 请写出Java中的8种基础数据类型的名称,以及占用的字节数量。

    数据类型byteshortintlongfloatdoublecharboolean
    字节12484821

  3. 请描述发生自动类型转换的条件。

    //字节小的数据类型向字节大的数据类型转换

    通过代码试验将较大的long类型的变量(值大于int型能够描述的最大数字)强制转换为int类型后的值是多少。

  4. 表达式123 + 456.58 + ”I am lucky”的值是多少?

    //579.5799999999999I am lucky
    
  5. 分析下面的程序运行结果

    1:byte b = 1;

    2:short s = 2;

    3:short x = s + b;

    第3行报错,因为
    ​
    •   short类型 + byte类型   = int类型
    ​
    •   short类型 + shrot类型  = int类型
    ​
    •   byte类型  + byte类型   = int类型
  6. 分析下面的程序运行结果

    short s = 1; //1在short范围内,所以可以赋值

    s = s + 1; //1是int类型,运算后提升到int类型,不能赋值给short类型

    答:short s = 1;//1在short范围内,所以可以赋值
    s = s + 1; //1是int类型,运算后提升到int类型,不能赋值给short类型

    分析下面的程序运行结果

    short s = 1; //1在short范围内,所以可以赋值

    s = 18 + 1; //18+1在编译时确定了其值在short范围内,因此可以赋值

    答:short s = 1;
    s = 18 + 1;//没有变量,不用进行数据转换
    

5. 本章内容总结

  • 3
    点赞
  • 13
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值