【Java从0到1学习】03 Java 基础知识

03 Java 基础知识

1. 关键字

关键字是编程语言里事先定义好并赋予了特殊含义的单词,也称作保留字。和其它语言一样,Java中保留了许多关键字,例如,class、public等,下面列举的是Java中所有的关键字。

1.1 关键字概述

被Java语言赋予特定含义的单词

1.2 关键字特点

组成关键字的字母全部小写

1.3 关键字注意事项

  • goto和const作为保留字存在,目前并不使用
  • 类似Notepad++这样的高级记事本,针对关键字有特殊的颜色标记,非常直观

用于定义数据类型的关键字

用于定义访问权限修饰符的关键字

java关键字

2. 标识符

2.1 标识符概述

就是给类,接口,方法,变量等起名字时使用的字符序列

2.2 组成规则

由英文大小写字母、数字字符、$(美元符号)、_(下划线)组成

2.3 注意事项

  • 不能以数字开头
  • 不能是Java中的关键字
  • 区分大小写

2.4 标识符常见命名规则:见名知意

2.4.1 包

其实就是文件夹,用于把相同的类名进行区分,全部小写,单级:liuyi,多级:cn.itcast

为了便于对硬盘上的文件进行管理,通常都会将文件分目录进行存放。同理,在程序开发中,也需要将编写的类在项目中分目录存放,以便于文件管理。为此,Java引入了包(package)机制,程序可以通过声明包的方式对Java类定义目录。

Java中的包是专门用来存放类的,通常功能相同的类存放在相同的包中。在声明包时,使用package语句,具体示例如下:

package cn.itcast.chapter01; // 使用package关键字声明包
public class Example01{
    
    }

需要注意的是,包的声明只能位于Java源文件的第一行。

在实际程序开发过程中,定义的类都是含有包名的,如果没有显式地声明package语句,创建的类则处于默认包下,在实际开发中,这种情况是不应该出现的,本文的示例代码主要展现的是功能部分的代码,所以在大多数示例代码中没有为示例指定包名,但是在提供的源码中,都已使用包名。

在开发时,一个项目中可能会使用很多包,当一个包中的类需要调用另一个包中的类时,就需要使用import关键字引入需要的类。使用import可以在程序中一次导入某个指定包下的类,这样就不必在每次用到该类时都书写完整类名,简化了代码量。使用import关键字的具体格式如下所示:

import 包名.类名;

需要注意的是,import通常出现在package语句之后,类定义之前。如果有时候需要用到一个包中的许多类,则可以使用 import 包名.*; 来导入该包下所有类。

在JDK中,不同功能的类都放在不同的包中,其中Java的核心类主要放在java包及其子包下,Java扩展的大部分类都放在javax包及其子包下。为了便于后面的学习,接下来简单介绍Java语言中的常用包。

  • java.util:包含Java中大量工具类、集合类等,例如Arrays、List、Set等。
  • java.net:包含Java网络编程相关的类和接口。
  • java.io:包含了Java输入、输出有关的类和接口。
  • java.awt:包含用于构建图形界面(GUI)的相关类和接口。

除了上面提到的常用包,JDK中还有很多其它的包,比如数据库编程的java.sql包,编写GUI的javax.swing包等等,JDK中所有包中的类构成了Java类库。在以后的章节中,这些包中的类和接口将逐渐介绍,这里只需要有个大致印象即可。

2.4.2 类或者接口

一个单词:单词的首字母必须大写,举例:Student,Dog
多个单词:每个单词的首字母必须大写举例:HelloWorld,StudentName

2.4.3 方法和变量

一个单词:单词的首字母小写,举例:main,age
多个单词:从第二个单词开始,每个单词的首字母大写,举例:studentAge,showAllNames()

2.4.4 常量

一个单词:全部大写,举例:PI
多个单词:每个字母都大写,用_隔开,举例:STUDENT_MAX_AGE

3. 注释

3.1 注释概述

用于解释说明程序的文字

3.2 Java中注释分类格式

  • 单行注释,格式: //注释文字
  • 多行注释,格式: /* 注释文字 */
  • 文档注释,格式:/** 注释文字 */
/*
	注释:用于解释说明程序的文字

	Java中注释的分类及格式
		单行注释://
		多行注释:/星 星/
			注意:多行不可以嵌套使用,而单行是可以的
		文档注释:被javadoc工具解析生成一个说明书,面向对象部分讲解。
*/

//这是我的注释案例
class ZhuShiDemo {
    
    
	//main方法是主方法
	//是程序的入口
	//被jvm调用
	public static void main(String[] args) {
    
    
		System.out.println("好好学习,天天向上");
	}
}
  • 对于单行和多行注释,被注释的文字,不会被JVM(java虚拟机)解释执行
  • 对于文档注释,是java特有的注释,其中注释内容可以被JDK提供的工具 javadoc 所解析,生成一套以网页文件形式体现的该程序的说明文档
  • 注释是一个程序员必须要具有的良好编程习惯
  • 初学者编写程序可以养成习惯:先写注释再写代码
  • 将自己的思想通过注释先整理出来,在用代码去体现
  • 因为代码仅仅是思想的一种体现形式而已
/*
	需求:我准备写一个java程序,把"HelloWorld"这句话输出在控制台

	分析:
		A:要写一个Java程序,必须定义类
		B:把数据能够输出,说明我们的程序是可以独立运行的,而程序要独立运行,必须定义main方法
		C:把数据输出在控制台,必须使用输出语句

	实现:
		A:java语言提供了一个关键字:class用来定义类,后面跟的是类名
		B:main方法的格式是固定的:
			public static void main(String[] args) {

			}
		C:输出语句的格式是固定的:
			System.out.println("HelloWorld");
			"HelloWorld"这个内容是可以改变的
*/

//这是我的HelloWorld案例
class HelloWorld {
    
    
	/*
		为了程序能够独立运行,定义main方法
		main方法是程序的入口
		被jvm自动调用
	*/
	public static void main(String[] args) {
    
    
		//为了把数据显示在控制台,我们就使用了输出语句
		System.out.println("HelloWorld");
	}
}

4. 常量、进制和进制转换

4.1 常量概述

在程序执行的过程中其值不可以发生改变

4.2 Java中常量分类

4.2.1 字面值常量

  • 字符串常量:用双引号括起来的内容,举例:“hello”,“world”
  • 整数常量:所有整数,举例:12,23
  • 小数常量:所有小数,举例:12.34,56.78
  • 字符常量:用单引号括起来的内容,举例:‘a’,’A’,’0’
  • 布尔常量,较为特有,举例:true,false
  • 空常量,举例:null

4.2.2 自定义常量

/*
	常量:
		在程序执行过程中,其值不发生改变的量。

	分类:
		A:字面值常量
		B:自定义常量(后面讲)

	字面值常量
		A:字符串常量	用双引号括起来的内容。
			举例:"hello","world","HelloWorld"
		B:整数常量	所有的整数
			举例:100,200
		C:小数常量	所有的小数
			举例:10.23,110.11
		D:字符常量	用单引号括起来的内容
			举例:'a','A','0'
			错误的:'ab'
		E:布尔常量	比较特殊
			举例:true,false
		F:空常量	后面讲
			举例:null
*/
class ConstantDemo {
    
    
	public static void main(String[] args) {
    
    
		//字符串常量的输出
		System.out.println("hello");

		//整数常量的输出
		System.out.println(100);

		//小数常量的输出
		System.out.println(100.10);

		//字符常量的输出
		System.out.println('a');
		System.out.println('A');
		System.out.println('0');
		//这个是有问题的
		//System.out.println('ab');

		//布尔常量的输出
		System.out.println(true);
		System.out.println(false);
	}
}

4.3 Java针对整数常量提供了4种表现形式

二进制,八进制,十进制,十六进制

4.4 进制概述

进制:就是进位制,是人们规定的一种进位方法。 对于任何一种进制–X进制,就表示某一位置上的数运算时是逢X进一位。二进制就是逢二进一,八进制是逢八进一,十进制是逢十进一,十六进制是逢十六进一。

PS:
二进制的由来:任何数据在计算机中都是以二进制的形式存在的。二进制早期由电信号开关演变而来。

一个整数在内存中一样也是二进制的,但是使用一大串的1或者0组成的数值进行使用很麻烦。所以就想把一大串缩短点,将二进制中的三位用一位表示。这三位可以取到的最大值就是7超过7就进位了,这就是八进制。但是对于过长的二进制变成八进制还是较长,所以出现的用4个二进制位表示一位的情况,四个二进制位最大是15,这就是十六进制。

规律:进制越大,表现形式越短。

4.5 不同进制的数据组成

  • 二进制,由0,1组成。以0b开头
  • 八进制,由0,1,…7组成。以0开头
  • 十进制,由0,1,…9组成。整数默认是十进制的
  • 十六进制,由0,1,…9,a,b,c,d,e,f(大小写均可)。以0x开头
/*
	不同进制的数据表现:
		二进制:由0,1组成。以0b开头。
		八进制:由0,1,...7组成。以0开头。
		十进制:由0,1,...9组成。默认整数是十进制。
		十六进制:由0,1,...9,a,b,c,d,e,f(大小写均可)组成。以0x开头。
*/
class JinZhiDemo {
    
    
	public static void main(String[] args) {
    
    
		System.out.println(100); //十进制

		System.out.println(0b100); //二进制
		System.out.println(0100); //八进制
		System.out.println(0x100); //十六进制
	}
}

运行结果

4.6 进制转换

  • 其他进制到十进制

  • 十进制到其他进制

  • 十进制和二进制的快速转换,8421码,也叫BCD码

  • 二进制和八进制,十六进制如何转换
    以十进制作为桥梁,二进制到八进制 3位组合,二进制到十六进制4位组合

PS:
1、其他进制到十进制

n转十进制公式:数值乘以进制的n-1次方,xyz=x*n^2+y*n^1+z*n^0

  • 系数xyz:就是每一位上的数据
  • 基数:n进制,基数就是n
  • 权:在右边,从0开始编号,对应位上的编号即为该位的权
  • 结果:把系数*基数的权次幂相加即可

例如八进制转十进制:0123=1*8^2 + 2*8^1 + 3*8^0

2、十进制到其他进制
除基取余,直到商为0,余数反转。

4.7 有符号数据表示法

在计算机内,有符号数有3种表示法:原码、反码和补码。所有数据的运算都是采用补码进行的

  • 原码:就是二进制定点表示法,即最高位为符号位,“0”表示正,“1”表示负,其余位表示数值的大小
  • 反码:正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外
  • 补码:正数的补码与其原码相同;负数的补码是在其反码的末位加1

4.8 练习

4.8.1 得到下面数据的十进制值

0b10101
   =1*2^4 + 1*2^2 + 1*2^0
   =16 + 4 + 1
   =21

0123
   =1*8^2 + 2*8^1 + 3*8^0
   =64 + 16 + 3
   =83

0x3c
   =3*16^1 + c*16^0
   =48 + 12
   =60

4.8.2 得到下面数据的二进制,十进制,十六进制

52分别得到二进制,十进制,十六进制

得到二进制:

   52 / 2 = 26      0
   26 / 2 = 13      0
   13 / 2 = 6       1
   6  / 2 = 3       0
   3  / 2 = 1       1
   1  / 2 = 0       1
   0b110100

得到八进制:

   52 / 8 = 6     4
   6  / 8 = 0    6
   064

得到十六进制:

   52 / 16 = 3   4
   3  / 16 = 0  3
   0x34

4.8.3 有符号数据表示法的练习

A:已知某数X的原码为10110100B,试求X的补码和反码。

符号位 数值位
原码:10110100
反码:11001011
补码:11001100

B:已知某数X的补码11101110B,试求其原码

符号位 数值位
补码: 11101110
反码: 11101101
原码: 10010010

5. 变量

在程序运行期间,随时可能产生一些临时数据,应用程序会将这些数据保存在一些内存单元中,每个内存单元都用一个标识符来标识。这些内存单元我们称之为变量,定义的标识符就是变量名,内存单元中存储的数据就是变量的值。

5.1 变量概述

在程序执行的过程中,在某个范围内其值可以发生改变的量,理解:如同数学中的未知数

5.2 变量定义格式

数据类型 变量名 = 初始化值;
注意:格式是固定的,记住格式,以不变应万变

5.3 变量的组成规则

1、从本质上讲,变量其实是内存中的一小块区域,使用变量名来访问这块区域,因此,每一个变量使用前必须要先申请(声明),然后必须进行赋值(填充内容),才能使用。通过画图说明一个变量的组成部分

数据类型,变量名,变量值

2、为什么要定义变量呢?用来不断的存放同一类型的常量,并可以重复使用

6. 数据类型和类型转换

Java是一门强类型的编程语言,它对变量的数据类型有严格的限定。在定义变量时必须声明变量的类型,在为变量赋值时必须赋予和变量同一种类型的值,否则程序会报错。

类型转换

6.1 数据类型

6.1.1 Java语言是强类型语言,对于每一种数据都定义了明确的具体数据类型,在内存总分配了不同大小的内存空间

6.1.2 所谓有效数字:具体地说,是指在分析工作中实际能够测量到的数字。所谓能够测量到的是包括最后一位估计的,不确定的数字。对于一个近似数,从左边第一个不是0的数字起,到精确到的位数止,所有的数字都叫做这个数的有效数字。

6.1.3 Java 各整数类型有固定的表数范围和字段长度,其不受具体操作系统的影响,以保证Java程序的可移植性。

  • Java语言的整型常量默认为int型,声明long型常量可以后加‘ l ’或‘ L ’ ,如:

    int i1 = 600; //正确 long l1 = 88888888888L; //必须加l否则会出错

  • 与整数类型类似,Java浮点类型有固定的表数范围和字段长度,不受平台影响。

    Java浮点类型常量有两种表示形式,十进制数形式,如: 3.14 314.0

  • 科学记数法形式,如 3.14e2 3.14*10^2

  • Java 浮点型常量默认为 double 型,如要声明一个常量为 float 型,则需在数字后面加 f 或 F ,如:

    double d = 12345.6; //正确 float f = 12.3f; //必须加f否则会出错

  • char 型数据用来表示通常意义上的“字符”

    • 字符常量为用单引号括起来的单个字符,例如:char ch1= ‘a’; char ch2=‘中’;
    • Java字符采用 Unicode 编码,每个字符占两个字节,因而可用十六进制编码形式表示。
    • 注:Unicode是全球语言统一编码
  • boolean 类型适于逻辑运算,一般用于程序流程控制 。

  • boolean 类型数据只允许取值 true 或 false ,不可以 0 或非 0 的整数替代 true 和 false ,这点和C语言不同。

  • 数据类型

    • 基本数据类型:整型byte、short、int、long,浮点型float、double,字符型char,布尔型boolean
    • 引用数据类型:类class、接口interface、数组[]

/*
	数据类型:Java是一种强类型的语言,针对每一种数据都定义了明确的数据类型。

	数据类型分类:
		A:基本数据类型
		B:引用数据类型(类,接口,数值)

	基本数据类型:4类8种
		A:整数			占用字节数
			byte			1
			short			2
			int				4
			long			8

		B:浮点数
			float 			4
			double 			8

		C:字符
			char			2
		D:布尔
			boolean			1

		注意:
			整数默认是int类型
			浮点数默认是double类型。

			长整型后缀用L或者l标记。建议使用L。
			单精度浮点数用F或者f标记。建议使用F。
*/
class DataTypeDemo {
	public static void main(String[] args) {
		//定义变量的格式:
		//数据类型 变量名 = 初始化值;

		//定义一个字节变量
		byte b = 10;
		System.out.println(10);
		System.out.println(b);

		//定义一个短整型变量
		short s = 100;
		System.out.println(s);

		//定义一个整型变量
		int i = 1000;
		System.out.println(i);

		//超过了int的范围
		//int j = 1000000000000;
		long j = 1000000000000L;
		//long j = 100L;
		System.out.println(j);

		//定义浮点数据变量
		float f = 12.345F;
		System.out.println(f);

		double d = 12.345;
		System.out.println(d);

		//定义字符变量
		char ch = 'a';
		System.out.println(ch);

		//定义布尔变量
		boolean flag = true;
		System.out.println(flag);
	}
}

运行结果:

6.1.4 使用变量的时候要注意的问题:

  • A:作用域
    变量定义在哪个大括号内,它就在这个大括号内有效。
    并且,在同一个大括号内不能同时定义同名的变量。

  • B:初始化值
    没有初始化值的变量不能直接使用。
    你只要在使用前给值就行,不一定非要在定义的时候立即给值。
    推荐在定义的时候给值。

    定义变量的格式:
    a:数据类型 变量名 = 初始化值;
    b:数据类型 变量名;
    变量名 = 初始化值;

  • C:在一行上建议只定义一个变量
    可以定义多个,但是不建议

6.2 类型转换

当把一种数据类型的值赋给另一种数据类型的变量时,需要进行数据类型转换。

根据转换方式的不同,数据类型转换可分为两种:自动类型转换和强制类型转换。

6.2.1 默认转换(从小到大的转换)

自动类型转换也叫隐式类型转换,指的是两种数据类型在转换的过程中不需要显式地进行声明。

要实现自动类型转换,必须同时满足两个条件

  • 第一是两种数据类型彼此兼容,
  • 第二是目标类型的取值范围大于源类型的取值范围。

(1)整数类型之间可以实现转换,如byte类型的数据可以赋值给short、int、long类型的变量,short、char类型的数据可以赋值给int、long类型的变量,int类型的数据可以赋值给long类型的变量
(2)整数类型转换为float类型,如byte、char、short、int类型的数据可以赋值给float类型的变量。
(3)其它类型转换为double类型,如byte、char、short、int、long、float类型的数据可以赋值给double类型的变量。

A:byte,short,char—int—long—float—double

B:byte,short,char相互之间不转换,他们参与运算首先转换为int类型

6.2.2 强制转换

强制类型转换也叫显式类型转换,指的是两种数据类型之间的转换需要进行显式地声明。

当两种类型彼此不兼容,或者目标类型取值范围小于源类型时,自动类型转换无法进行,这时就需要进行强制类型转换。

从大的数据类型到小的数据类型
格式:目标数据类型 变量 = (目标数据类型) (被转换的数据);
注意:不要随意的去使用强制转换,因为它隐含了精度损失问题

/*
	面试题:
		byte b1=3,b2=4,b;
		b=b1+b2;
		b=3+4;
		哪句是编译失败的呢?为什么呢?
		b = b1 + b2;是有问题的。
		因为变量相加,会首先看类型问题,最终把结果赋值的也会考虑类型问题。
		常量相加,首先做加法,然后看结果是否在赋值的数据类型范围内,如果不是,才报错。
*/
class DataTypeDemo6 {
    
    
	public static void main(String[] args) {
    
    
		//定义了三个byte类型的变量,b1,b2,b3
		//b1的值是3,b2的值是4,b没有值
		byte b1 = 3,b2 = 4,b;

		//b = b1 + b2; //这个是类型提升,所有有问题

		b = 3 + 4; //常量,先把结果计算出来,然后看是否在byte的范围内,如果在就不报错。
	}
}

1、在定义Long或者Float类型变量的时候,要加L或者f。

  • 整数默认是int类型,浮点数默认是double。
  • byte,short在定义的时候,他们接收的其实是一个int类型的值。
  • 这个是自己做了一个数据检测的,如果不再它们的范围内,就报错。

2、byte值的问题

byte b1 = 127;
byte b2 = (byte)128; //-128
byte b3 = (byte)129; //-127
byte b4 = (byte)130; //-126
byte的范围:-128 ~ 127
12810000000
-12810000000 (这里的1即是符号位,也是数值位)

3、数据类型转换之默认转换
byte,short,char – int – long – float – double
long:8个字节
float:4个字节
A:它们底层的存储结构不同
B:float表示的数据范围比long的范围要大
long:2^63-1
float:3.4*10^38 > 2*10^38 > 2*8^38 = 2*2338 = 2*2^114 > 2^63-1

4、Java语言中的字符char可以存储一个中文汉字吗?为什么呢?
可以。因为java语言中的字符占用两个字节。Java语言采用的是Unicode编码。

7. 运算符

7.1 运算符

  • 运算:对常量和变量进行操作的过程称为运算。
  • 运算符:对常量和变量进行操作的符号称为运算符
  • 操作数:参与运算的数据称为操作数
  • 用运算符把常量或者变量连接起来符号java语法的式子就可以称为表达式。
    不同运算符连接的式子体现的是不同类型的表达式。

举例:int a = 3 + 4;
这是做了一个加法运算,+就是运算符,是算术运算符,我们还有其他很多的运算符,3和4就是参与运算的操作数据,3 + 4整体其实就是一个算数表达式

7.2 算术运算符

算术运算符

除法的时候要注意一个问题,整数相除,只能得到整数,要想得到小数,可以*1.0

  • ++和–的应用
    单独使用:放在操作数的前面和后面效果一样。(这种用法是我们比较常见的)
    参与运算使用:放在操作数的前面,先自增或者自减,然后再参与运算;放在操作数的后面,先参与运算,再自增或者自减。
    作用:就是对变量进行自增1或者自减1。
  • +的用法:加法,正号,字符串连接符
  • 运算符的优先级(由高到低)

运算符的优先级

7.3 赋值运算符

基本的赋值运算符:=,把=右边的数据赋值给左边。
扩展的赋值运算符:+=、-=,*=,/=,%=,+= 把左边和右边做加法,然后赋值给左边。

7.4 关系运算符

关系运算符

  • 比较运算符的结果都是boolean型,也就是要么是true,要么是false。
  • 比较运算符“==”不能误写成“=”

7.5 逻辑运算符

逻辑运算符

  • 逻辑运算符用于连接布尔型表达式,在Java中不可以写成 3<x<6,应该写成x>3 & x<6 。
  • “&”和“&&”的区别
    • 单&时,左边无论真假,右边都进行运算
    • 双&时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算
    • “|”和“||”的区别同理,双或时,左边为真,右边不参与运算
  • 异或( ^ )与或( | )的不同之处是:当左右都为true时,结果为false

7.6 位运算符

位运算是直接对二进制进行运算

位运算符

位运算符的细节

/*
	位运算符:
		&,|,^,~
		<<,>>,>>>

	注意:
		要做位运算,首先要把数据转换为二进制。
*/
class OperatorDemo {
    
    
	public static void main(String[] args) {
    
    
		//&,|,^,~

		int a = 3;
		int b = 4;

		System.out.println(3 & 4);
		System.out.println(3 | 4);
		System.out.println(3 ^ 4);
		System.out.println(~3);
	}
}
/*
	分析:因为是位运算,所以我们必须先把数据换算成二进制。

	3的二进制:11
		00000000 00000000 00000000 00000011
	4的二进制:100
		00000000 00000000 00000000 00000100

	&位与运算:有0则0。
		00000000 00000000 00000000 00000011
	   &00000000 00000000 00000000 00000100
		-----------------------------------
		00000000 00000000 00000000 00000000
		结果是:0

	|位或运算:有1则1。
		00000000 00000000 00000000 00000011
	   |00000000 00000000 00000000 00000100
		-----------------------------------
		00000000 00000000 00000000 00000111
		结果是:7

	^位异或运算:相同则0,不同则1。
		00000000 00000000 00000000 00000011
	   &00000000 00000000 00000000 00000100
		-----------------------------------
		00000000 00000000 00000000 00000111
		结果是:7

	~按位取反运算符:0变1,1变0
		00000000 00000000 00000000 00000011
	   ~11111111 11111111 11111111 11111100 (补码)

	   补码:11111111 11111111 11111111 11111100
	   反码:11111111 11111111 11111111 11111011
	   原码:10000000 00000000 00000000 00000100
	   结果是:-4
*/

7.7 三目运算符

  • 格式:(关系表达式)?表达式1:表达式2;
    • 如果条件为true,运算后的结果是表达式1;
    • 如果条件为false,运算后的结果是表达式2;
  • 示例:获取两个数中大数。
int x=3,y=4,z;
z = (x>y)?x:y;//z变量存储的就是两个数的大数。

7.8 运算符的优先级

在对一些比较复杂的表达式进行运算时,要明确表达式中所有运算符参与运算的先后顺序,把这种顺序称作运算符的优先级。

1500703686246

7.9 Math

Math类提供了常用的一些数学函数,如:三角函数、对数、指数等。一个数学公式如果想用代码表示,则可以将其拆分然后套用Math类下的方法即可。

Math.abs(12.3);                 //12.3 返回这个数的绝对值  
Math.abs(-12.3);                //12.3  
  
Math.copySign(1.23, -12.3);     //-1.23,返回第一个参数的量值和第二个参数的符号  
Math.copySign(-12.3, 1.23);     //12.3  
  
Math.signum(x);                 //如果x大于0则返回1.0,小于0则返回-1.0,等于0则返回0  
Math.signum(12.3);              //1.0  
Math.signum(-12.3);             //-1.0  
Math.signum(0);                 //0.0  
  
  
//指数  
Math.exp(x);                    //e的x次幂  
Math.expm1(x);                  //e的x次幂 - 1  
  
Math.scalb(x, y);               //x*(2的y次幂)  
Math.scalb(12.3, 3);            //12.3*2³  
  
//取整  
Math.ceil(12.3);                //返回最近的且大于这个数的整数13.0  
Math.ceil(-12.3);               //-12.0  
  
Math.floor(12.3);               //返回最近的且小于这个数的整数12.0  
Math.floor(-12.3);              //-13.0  
  
//x和y平方和的二次方根  
Math.hypot(x, y);               //√(x²+y²)  
  
//返回概述的二次方根  
Math.sqrt(x);                   //√(x) x的二次方根  
Math.sqrt(9);                   //3.0  
Math.sqrt(16);                  //4.0  
  
//返回该数的立方根  
Math.cbrt(27.0);                //3   
Math.cbrt(-125.0);              //-5  
  
//对数函数  
Math.log(e);                    //1 以e为底的对数  
Math.log10(100);                //10 以10为底的对数  
Math.log1p(x);                  //Ln(x+ 1)  
  
//返回较大值和较小值  
Math.max(x, y);                 //返回x、y中较大的那个数  
Math.min(x, y);                 //返回x、y中较小的那个数  
  
//返回 x的y次幂  
Math.pow(x, y);                   
Math.pow(2, 3);                 //即2³ 即返回:8  
  
//随机返回[0,1)之间的无符号double值  
Math.random();                    
  
//返回最接近这个数的整数,如果刚好居中,则取偶数  
Math.rint(12.3);                //12.0   
Math.rint(-12.3);               //-12.0  
Math.rint(78.9);                //79.0  
Math.rint(-78.9);               //-79.0  
Math.rint(34.5);                //34.0  
Math.rint(35.5);                //36.0  
  
Math.round(12.3);               //与rint相似,返回值为long  
  
//三角函数  
Math.sin(α);                    //sin(α)的值  
Math.cos(α);                    //cos(α)的值  
Math.tan(α);                    //tan(α)的值  
  
//求角  
Math.asin(x/z);                 //返回角度值[-π/2,π/2]  arc sin(x/z)  
Math.acos(y/z);                 //返回角度值[0~π]   arc cos(y/z)  
Math.atan(y/x);                 //返回角度值[-π/2,π/2]  
Math.atan2(y-y0, x-x0);         //同上,返回经过点(x,y)与原点的的直线和经过点(x0,y0)与原点的直线之间所成的夹角  
  
Math.sinh(x);                   //双曲正弦函数sinh(x)=(exp(x) - exp(-x)) / 2.0;  
Math.cosh(x);                   //双曲余弦函数cosh(x)=(exp(x) + exp(-x)) / 2.0;  
Math.tanh(x);                   //tanh(x) = sinh(x) / cosh(x);  
  
//角度弧度互换  360°角=2π弧度
Math.toDegrees(angrad);         //角度转换成弧度,返回:angrad * 180d / PI  
  
Math.toRadians(angdeg);         //弧度转换成角度,返回:angdeg / 180d * PI  

Math.PI

8. 修饰符

java修饰符

Java语言提供了很多修饰符,主要分为以下两类:

  • 访问修饰符
  • 非访问修饰符

修饰符用来定义类、方法或者变量,通常放在语句的最前端。我们通过下面的例子来说明:

public class ClassName {
    
    
   // ...
}
private boolean myFlag;
static final double weeks = 9.5;
protected static final int BOXWIDTH = 42;
public static void main(String[] arguments) {
    
    
   // 方法体
}

8.1 访问控制修饰符

Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

  • default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
  • private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
  • public : 对所有类可见。使用对象:类、接口、变量、方法
  • protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)

我们可以通过以下表来说明访问权限:

修饰符 当前类 同一包内 子孙类(同一包) 子孙类(不同包) 其他包
public Y Y Y Y Y
protected Y Y Y Y/N N
default Y Y Y N N
private Y N N N N

8.1.1 默认访问修饰符-不使用任何关键字

如果在类、变量、方法或构造函数的定义中没有指定任何访问修饰符,那么它们就默认具有默认访问修饰符。

默认访问修饰符的访问级别是包级别(package-level),即只能被同一包中的其他类访问。

如下例所示,变量和方法的声明可以不使用任何修饰符。

// MyClass.java
 
class MyClass {
    
      // 默认访问修饰符
 
    int x = 10;  // 默认访问修饰符
 
    void display() {
    
      // 默认访问修饰符
        System.out.println("Value of x is: " + x);
    }
}
 
// MyOtherClass.java
 
class MyOtherClass {
    
    
    public static void main(String[] args) {
    
    
        MyClass obj = new MyClass();
        obj.display();  // 访问 MyClass 中的默认访问修饰符变量和方法
    }
}

8.1.2 私有访问修饰符-private

私有访问修饰符是最严格的访问级别,所以被声明为 private 的方法、变量和构造方法只能被所属类访问,并且类和接口不能声明为 private

声明为私有访问类型的变量只能通过类中公共的 getter 方法被外部类访问。

Private 访问修饰符的使用主要用来隐藏类的实现细节和保护类的数据。

下面的类使用了私有访问修饰符:

public class Logger {
    
    
   private String format;
   public String getFormat() {
    
    
      return this.format;
   }
   public void setFormat(String format) {
    
    
      this.format = format;
   }
}

实例中,Logger 类中的 format 变量为私有变量,所以其他类不能直接得到和设置该变量的值。为了使其他类能够操作该变量,定义了两个 public 方法:getFormat() (返回 format的值)和 setFormat(String)(设置 format 的值)

8.1.3 公有访问修饰符-public

被声明为 public 的类、方法、构造方法和接口能够被任何其他类访问。

如果几个相互访问的 public 类分布在不同的包中,则需要导入相应 public 类所在的包。由于类的继承性,类所有的公有方法和变量都能被其子类继承。

以下函数使用了公有访问控制:

public static void main(String[] arguments) {
    
    
   // ...
}

Java 程序的 main() 方法必须设置成公有的,否则,Java 解释器将不能运行该类。

8.1.4 受保护的访问修饰符-protected

protected 需要从以下两个点来分析说明:

  • 子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问;
  • 子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法。

protected 可以修饰数据成员,构造方法,方法成员,不能修饰类(内部类除外)

接口及接口的成员变量和成员方法不能声明为 protected。

子类能访问 protected 修饰符声明的方法和变量,这样就能保护不相关的类使用这些方法和变量。

下面的父类使用了 protected 访问修饰符,子类重写了父类的 openSpeaker() 方法。

class AudioPlayer {
    
    
   protected boolean openSpeaker(Speaker sp) {
    
    
      // 实现细节
   }
}
 
class StreamingAudioPlayer extends AudioPlayer {
    
    
   protected boolean openSpeaker(Speaker sp) {
    
    
      // 实现细节
   }
}

如果把 openSpeaker() 方法声明为 private,那么除了 AudioPlayer 外,其他类将不能访问该方法。

如果把 openSpeaker() 声明为 public,那么所有的类都能够访问该方法。

如果我们只想让该方法对其所在类的子类可见,则将该方法声明为 protected。

8.1.5 访问控制和继承

请注意以下方法继承的规则:

  • 父类中声明为 public 的方法在子类中也必须为 public。
  • 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
  • 父类中声明为 private 的方法,不能够被子类继承。

8.2 非访问修饰符

为了实现一些其他的功能,Java 也提供了许多非访问修饰符。

static 修饰符,用来修饰类方法和类变量。

final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。

abstract 修饰符,用来创建抽象类和抽象方法。

synchronized 和 volatile 修饰符,主要用于线程的编程。

8.2.1 static 修饰符

  • 静态变量:

    static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为 static 变量。

  • 静态方法:

    static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。

对类变量和方法的访问可以直接使用 classname.variablenameclassname.methodname 的方式访问。

如下例所示,static 修饰符用来创建类方法和类变量。

public class InstanceCounter {
    
    
   private static int numInstances = 0;
   protected static int getCount() {
    
    
      return numInstances;
   }
 
   private static void addInstance() {
    
    
      numInstances++;
   }
 
   InstanceCounter() {
    
    
      InstanceCounter.addInstance();
   }
 
   public static void main(String[] arguments) {
    
    
      System.out.println("Starting with " +
      InstanceCounter.getCount() + " instances");
      for (int i = 0; i < 500; ++i){
    
    
         new InstanceCounter();
          }
      System.out.println("Created " +
      InstanceCounter.getCount() + " instances");
   }
}

以上实例运行编辑结果如下:

Starting with 0 instances
Created 500 instances

8.2.2 final 修饰符

final 变量:

final 表示"最后的、最终的"含义,变量一旦赋值后,不能被重新赋值。被 final 修饰的实例变量必须显式指定初始值。

final 修饰符通常和 static 修饰符一起使用来创建类常量。

public class Test{
    
    
  final int value = 10;
  // 下面是声明常量的实例
  public static final int BOXWIDTH = 6;
  static final String TITLE = "Manager";
 
  public void changeValue(){
    
    
     value = 12; //将输出一个错误
  }
}

final 方法

父类中的 final 方法可以被子类继承,但是不能被子类重写。

声明 final 方法的主要目的是防止该方法的内容被修改。

如下所示,使用 final 修饰符声明方法。

public class Test{
    
    
    public final void changeName(){
    
    
       // 方法体
    }
}

final 类

final 类不能被继承,没有类能够继承 final 类的任何特性。

public final class Test {
    
    
   // 类体
}

8.2.3 abstract 修饰符

抽象类:

抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。

一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误。

抽象类可以包含抽象方法和非抽象方法。

abstract class Caravan{
    
    
   private double price;
   private String model;
   private String year;
   public abstract void goFast(); //抽象方法
   public abstract void changeColor();
}

抽象方法

抽象方法是一种没有任何实现的方法,该方法的具体实现由子类提供。

抽象方法不能被声明成 final 和 static。

任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。

如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。

抽象方法的声明以分号结尾,例如:public abstract sample();

public abstract class SuperClass{
    
    
    abstract void m(); //抽象方法
}
 
class SubClass extends SuperClass{
    
    
     //实现抽象方法
      void m(){
    
    
          .........
      }
}

8.2.4 synchronized 修饰符

synchronized 关键字声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符。

public synchronized void showDetails(){
    
    
.......
}

8.2.5 transient 修饰符

序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。

该修饰符包含在定义变量的语句中,用来预处理类和变量的数据类型。

public transient int limit = 55;   // 不会持久化
public int b; // 持久化

8.2.6 volatile 修饰符

volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。

一个 volatile 对象引用可能是 null。

public class MyRunnable implements Runnable
{
    
    
    private volatile boolean active;
    public void run()
    {
    
    
        active = true;
        while (active) // 第一行
        {
    
    
            // 代码
        }
    }
    public void stop()
    {
    
    
        active = false; // 第二行
    }
}

通常情况下,在一个线程调用 run() 方法(在 Runnable 开启的线程),在另一个线程调用 stop() 方法。 如果 *第一行* 中缓冲区的 active 值被使用,那么在 *第二行* 的 active 值为 false 时循环不会停止。

但是以上代码中我们使用了 volatile 修饰 active,所以该循环会停止。

猜你喜欢

转载自blog.csdn.net/qq_34988304/article/details/131800973