Java main 函数
public class Main {
public static void main(String[] args) {
System.out.printf("Hello and welcome!");
}
}
与C++命名规范不同,Java 的命名形式最好使用驼峰法
Java 注释
C/C++常用的两种注释习惯Java都可以使用,Java自身还有一种文档注释,常用与方法和类之上描述方法和类的作用,可以被javadoc工具解析,生成一套以网页文件形式体现的程序说明文档
/**
* author clx
* version 1.0
*/
Java 数据类型
数据类型 | 关键字 | 内存占用 | 范围 |
---|---|---|---|
字节型 | byte | 1字节 | -128-127 |
短整形 | short | 2字节 | -32768 ~ 32767 |
整形 | int | 4字节 | -2^ 31 - 2^31 - 1 |
长整形 | long | 8字节 | -2^ 63 - 2^63 - 1 |
单精度浮点数 | float | 4字节 | 有范围,一般不关注 |
双精度浮点数 | double | 8字节 | 有范围,一般不关注 |
字符型 | char | 2字节 | 0 - 65535 |
布尔型 | boolean | 没有明确规定 | true 和 false |
空常量 | null |
1、long字节在C语言中的字节数是随编译器的,不确定的。而Java中时规定了四个字节
2、推荐变量一定义就进行初始化,如果没有合适的可以设置成0
3、int的包装类是Integer 【int 的加强版本】是一个类,包含了很多方法
4、char的包装类型为Character
4、Java中我们可以将数据类型的关键字第一个字母大写,就可以获得一个加强类,其中有好多方法
长整形变量
long 的包装类型是 Long
长整形变量的初始值后面+L (推荐)或者+l,不加默认int类型
long v1 = 10L;
字符型变量
char 包装类型为Character
和C语言使用ASCII表示字符相比,Java中使用Unicode表示自负,因此一个字符占用两个字节,表示的字符种类非常多,包括中文
char ch = '黄';
char ch1 = 100;
// char ch2 = -100; 错误,不能是负数
在执行 javac 时加上 -encoding UTF-8 选项即可:javac -encoding UTF-8 Test.java
布尔型变量
boolean在JVM中没有给定大小,但是Boolean数组,会被JVM识别成字节数组,所以一个boolean占一个字节/一个比特位是正确的
Java中的boolean类型不能和int类型相互转换,不存在1表示真,0表示假
Oracle虚拟机实现中,boolean占一个字节
类型转换
Java 也是一个强类型的编程语言,当不同类型之间的变量相互赋值的时候,会有严格的校验,当参与运算数据类型不一致时,就会进行类型转换。
并且Java在常量赋值时,会自动针对数字范围进行检查
隐式类型转换
代码不需要进行任何处理,在代码编译时,编译器会自动处理
- int 和 long之间的转换
- float和double之间的转换
- Java不会像C++那样对数据进行阶段,数据范围由小到大,可以进行饮食类型转换,数据类型由大到小,则需要强转
强制类型转换
代码类型转换需要进行格式化处理,不能自动完成
比如将范围大的数值类型强转成小的数值类型,会发生截断或者精读丢失
byte b1 = (byte)257;
类型提升
和C相同,不同数据之间相互运算时,数据类型小的会被提升到数据类型大的,Java中也会将不足int类型的整形提升到int进行计算,而Java 不能像C那样进行隐式截断,导致不足int整形运算需要强转,比如下面的例子2
1、long 与 int 类型变量进行运算,int会被提升成long
2、byte 类型 和 byte类型进行运算
byte a = 10;
byte b = 20;
// byte c = a + b; 错误写法
byte c = (byte)(a + b); // 提升成int类型进行相加,转换成byte类型需要强制类型转换
类型提升到四字节并非Java特性,而是由于计算机的CPU通常是按照4个字节为单位从内存中读写数据,为了硬件上的实现方便,如byte和short这种低于4字节的类型,会被提升到int,再参与计算
字符串类型
Java中String类定义字符串类型:
String 类基本使用
int a = 520;
int b = 1314;
System.out.printfln("a =" + a + "b = " + b);
System.out.println("a + b = " + a + b);
这里可以看到Java中的print函数和pirntf函数是有区别的,前者通过+号将每个部分链接起来,而printf是通过解析格式化字符串来进行一个参数匹配字符串的构建
int 类型转成 String类型
在C++中我们可以通过to_string函数,也可以通过stringstream流来进行int类型转换成字符串类型,在Java中我们通常使用以下几种方法
方法一:隐式类型转换
int num = 1;
String str1 = num + "";
System.out.println(str1);
直接把num赋值给str1是行不通的,需要附加一个双引号(字符串)进行嫁接,表示转换成字符串类型,这个双引号可以在前也可以在后,当然也可以是一串字符串
方法二:调用String类的成员函数,使用包装类型内部valueOf成员函数是类型转换的常用手段
String str2 = String.valueOf(num);
String 转换成int
同上述方法2,使用Integer内部的成员函数valueOf()
String str = "123";
int a = Integer.valueOf(str);
System.out.println(a + 1);
若我们的str不是一个合法的数字,那么在进行转换的时候会抛出异常
运算符
Java中的运算符和C++中的运算符使用是几乎一摸一样的,但是移位运算符有有三个 << >> >>>
其中主要就是>>> 没有见过
>>>
表示无符号右移:因为在右移(>>
)中,左侧缺失的数是根据符号位来进行补齐的,符号位为1则最左边补上一个1反之补上0.
而无符号右移不管是正数还是负数,符号位为啥,统统补0
然后就是Java中也是支持条件运算符的表达式1?表达式2:表达式3
,这个是Java中唯一一个三目运算符
Java中的输入
在上文中我们知道了可以使用System
类中的out
成员的成员函数printf
进行输出,那么Java中到底是怎么进行输入的呢
我们可以使用Java中的工具类中的Scanner成员帮助我们从System.in获取输入,和C语言中的scanf有一点点像
Scanner是一个类,Java中也有类似头文件的语句,需要引用一下
import java.util.Scanner; // 引用一下这个类
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in); // 构建对象
int year = scan.nextInt(); // 使用nextInt()获取输入
System.out.println(year);
}
}
这里介绍一下
next()
--> 遇到空格读取结束,默认String类型,其后也可以加指定数据类型用于读取整数,浮点数之类的
nextLen()
– > 读到\n就结束
判断读取结束
while (scanf("%d", &y) != EOF) // C语言判断方式
while (cin >> n) // C++通过重载bool操作符
while (scan.hasNextInt()) // Java的判断方式
我们可以通过Ctrl + d让程序停止,Ctrl + c中断程序
Java方法
Java中的方法,类似于C语言的函数
1、模块化组织代码
2、做到代码复用,一份代码多处使用,增加开发效率
3、让代码更好理解
4、可以直接调用现有方法进行开发,不必重复造轮子
方法的定义与法
public static 返回值类型 方法名 (形式参数列表) {
方法体;
}
public static int my_add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
int c = my_add(1, 2);
System.out.println(c);
}
- 修饰符:初级阶段直接使用 public static 固定搭配
- 返回值类型:如果方法有返回值,返回值类型必须要与返回的实体类型一致,如果没有返回值,必须写成void
- 方法名字:采用小驼峰命名(第一个单词首字符小写,其余单词首字符大写)
在Java中,方法必须要写在类中,方法不可以嵌套定义,并且在Java中方法没有声明一说
Java 数组
数组存放的元素类型相同,空间连续,每个空间都有自己的编号
数组的创建及初始化
T[] 数组名 = new T[N];
1、我们可以直接指定数组元素个数,开辟空间会自动设置默认初始值,使用这种方式开辟
// int[] arr1 = new int[5]{ 1, 2 ,3 , 4, 5}; 错误写法
int[] arr1 = new int[5];
2、我们也可以不指定数组的元素个数,直接将具体的数据内容进行指定
int[] arr2 = new int[]{1, 2, 3, 4, 5}; // 完整写法
int[] arr3 = {1, 2, 3, 4, 5}; // 简洁写法
其中简洁写法使用的最广,虽然省略了new T[], 但是编译器编译时会还原
获取数组长度
我们可以根据数组对象的length成员变量进行获取数组长度
打印数组
出了可以通过遍历,我们还可以借助Java本身提供的一些方法来实现数组的打印
工具类Arrays,主要用来帮助我们操作数组
double[] arr = new double[]{1.0, 1.1, 1.2};
String s = Arrays.toString(arr);
System.out.println(s);
可以看到Array.toString 方法内部帮助我们对元素进行组装
引用类型
初始JVM对内存分布
内存是一段连续的存储空间,主要用来存储程序运行时的数据。程序中的有些数据可能需要长时间存储,而有些数据当方法运行结束后就要销毁
当我们生成一个Java文件,在编译的过程中输入命令Javac文件名.java就会生成一个.class 的字节码文件,那么这个文件就是在JVM中的Java本地方法栈上执行的。JVM使用的内存按照功能进行不同区域的划分
- Java虚拟机栈 与方法调用相关的一些信息,每个方法执行前都会先创建一个栈帧,栈帧中包含局部变量表,操作数栈,动态链接,返回地址等一些信息。当方法运行结束后,栈帧就被i销毁了,即栈帧中保存的数据也就被销毁了
- Java本地方法栈:本地方法栈的作用和虚拟机栈的租用类似,不过保存的内容是Native方法的局部变量。有些版本的JVM本地方法栈和虚拟机栈时一起的,运行一些C/C++代码编写的程序(JVM其实是一个软件,由C/C++代码编写的软件)
- 堆:JVM管理的最大内存区域,使用new创建的对象都是在堆上保存的,堆是随着程序开始运行时而创建,随着程序退出而销毁,堆中的数据之遥还在使用就不会销毁(只要是对象就在堆上分配内存)
- 程序计数器(PC Register):只是一个很小的空间,保存下一条指令的地址
- 方法区:用于存储易经被虚拟机加载的类信息、常量、静态变量、编译器编译后的代码等数据。方法编译出的字节码就是保存在这个位置
现在我们只关心堆和虚拟机栈堆两块空间
引用变量
基本数据类型创建堆变量称为基本变量,而引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在的空间的地址
double[] arr = new double[]{1.0, 1.1, 1.2}; System.out.println(arr); // [D@2a84aee7
Java中的数组就是引用数据类型,引用数据类型真实的地址是取不到的,只能去到对应的哈希值。
所以引用变量并不直接存储对象的本身,可以简单理解成存储对象在堆中空间的其实地址。通过地址,引用变量便可以去操作对象
我们可以通过下面这段代码理解
arr2 指向了 arr1引用的对象,因为两者中存储的都是对象的地址的对应哈希值,所以不能说是引用指向引用
double[] arr1 = new double[]{1.0, 1.1, 1.2};
double[] arr2 = arr1;
System.out.println(Arrays.toString(arr1)); // [1.0, 1.1, 1.2]
System.out.println(Arrays.toString(arr2)); // [1.0, 1.1, 1.2]
System.out.println((arr1)); // [D@2a84aee7
System.out.println((arr2)); // [D@2a84aee7
null
null 在 Java中表示 “空引用”, 也就是一个不指向对象的引用
int[] arr3 = null;
System.out.println(arr3); // null
// System.out.println(arr3.length); 空引用不可以取length,异常
当我们看到发生了空指针异常,我们就应该找前面看哪个引用是空的
总结:引用是一个常量,里面存的是地址
数组的应用场景
1、保存数据:数据的存储和输出
2、作为函数的参数
3、作为函数的返回值
Java 类和对象
类的定义
class Person {
// 属性:成员变量
public String _name;
public int age;
// 成员方法
public String get_name() {
return _name;
}
};
注意:
- Java开发中一般一个文件当中只定义一个类
- main方法所在的类一般要使用public修饰(Eclipse默认会在public修饰的类中寻找main方法)
- public修饰的类必须要和文件名相同
- 不要轻易修改public修饰的类名称,如果需要修改,通过开发者工具修改(先在文件名中修改,然后再把类名进行修改)
类成员初始值
如果我们创建了一个对象,但是没有对齐其进行初始化,直接打印出来的属性会是她们对应的0值(引用 – null, boolean – false , char – 0)
Person p = new Person();
System.out.println("1" + p.ch + "2"); // 12
如果是一个变量没有进行初始化,是不能直接使用的
char ch;
// System.out.println("1" + ch + "2"); 错误,使用没有初始化变量
this 引用
类似于C++中成员函数自带的this指针
java编译器会给每个成员方法增加一个隐藏的引用类型参数,该医用参数指向的对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问
所以在成员函数中this代表对当前对象的引用,可以区别当参数名称和成员名称相同时,谁为参数谁为成员。
this本质来说是一个隐式的参数(编译器自动添加,不需要我们显式的给出),是第一个参数
this 引用的特性
1、this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
2、this只能在成员方法中使用,不能在静态成员方法(static)中使用
3、在成员方法中,this只能引用当前对象,不能引用其他对象,具有final属性
4、this是成员第一个隐藏参数,编译器会自动传递
5、this(); 显式调用构造方法,在一个类拥有多个构造函数时,我们可以通过显示调用this()来构造简化代码
对象的构造和初始化