1.JRE和JVM的区别
- JRE(Java Runtime Environment,Java运行环境)包括Java虚拟机(JVM)和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机只需要安装JRE即可。
- JDK(Java Development Kit,Java开发包)是提供给Java开发人员使用的,其中包含了Java的开发工具,也包括了JRE。所以安装了JDK,就不需要单独安装JRE了。其中的开发工具包括:编译工具(javac.exe),打包工具(jar.exe)等
简而言之:使用JDK开发完成java程序,交给JRE去运行
2.第一个java程序,HelloWorld.java
class HelloWorld{
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
1.文件名最好必须要与类名相同
2.java的入口是执行main函数
执行
javac HelloWorld.java # 编译,生成class字节码文件
java HelloWorld # 执行class文件
3.数据类型
- 基本数据类型
数值型:byte(1),short(2),int(4),long(8),float(4),double(8)
字符型:char(2)
布尔型:boolean - 引用数据类型
类class
接口interface
数组[]
整数默认:int,小数默认:double
long i = 10000000000 // 10000000000默认是int,所以不能赋给long
long i = 10000000000L
float j = 12.345 //12.245默认是double,赋值给float会损失精度
float j = 12.345F
4.变量作用域
- 变量定义在哪个大括号内,它就在这个大括号内有效
- 在同一个大括号内不能同时定义同名的变量
类型转换
- 隐式转换
byte a = 10
int b = 20
int c = a+b // a会提升为int类型
- 强制转换
byte i = 10000; //错误,损失精度
byte i = (byte)(10000); //强制转换
System.out.println(i); // 16
注意:
float f1 = (float)12.245 //f1其实是通过一个double类型转换过来的
float f1 = 12.245F // f2本身就是一个float
- 在定义Long或者Float类型变量的时候,要加L或者F
整数默认是int类型,浮点数默认是double
byte,short在定义的时候,他们接收的其实是int类型的值,这个是自己做了一个数据检测的,如果不再它们的范围内,就报错
float和double的存储结构
易错知识
s+=1等价于 s = (s的数据类型)(s+1)
例如:
short s = 10
s = s + 2; // 报错
s+=2; // 正确
键盘录入程序
import java.util.Scanner;
public class HelloWorld {
public static void main(String[] args) {
System.out.println("请输入数字");
Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
System.out.println("你输入的数字是"+x);
}
}
Java中的内存分配
Java程序为了提高程序的效率,就对数据进行了不同空间的分配,具体划分为五个内存划分
- 栈:存储局部变量,由操作系统回收
- 堆:存储new出来的东西,有java虚拟机回收
- 方法区
- 本地方法区,和系统相关
- 寄存器:给CPU使用
局部变量:在方法定义中或者方法声明上的变量
堆内存的特点:
A:每一个new出来的东西都有地址值
B:每个变量都有默认值
C:使用完毕后就变成垃圾,但是并没有立即回收。会在垃圾回收器空闲的时候回收
栈内存的数据用完就释放
成员变量和局部变量的区别
class Student{
int age; // 成员变量
public static void study(){
int num = 10; //局部变量
}
}
成员变量和局部变量的区别?
- 在类中的位置不同
- 成员变量:类中方法外
- 局部变量:方法内部或者方法声明上
- 在内存中的位置不同
- 成员变量:堆内存
- 局部变量:栈内存
- 生命周期不同
- 成员变量:随着对象的存在而存在,随着对象的消失而消失
- 局部变量:随着方法的调用而存在,随着方法的调用而完毕而消失
- 初始化不同
- 成员变量有默认的初始值
- 局部变量没有默认的初始值,必须先定义,赋值,才能使用
匿名对象
没有名字的对象
new Student
匿名对象的应用场景
- 调用方法,只调用一次
new Student().study(); // 调用完成之后会被回收,没有指针指向(记住GC中的标记清除) - 匿名对象可以作为参数传递
构造方法
类的组成
1.成员变量
2.构造方法
3.成员方法
类的初始化过程
Student s = new Student();在内存中做了哪些事情?
- 加载Student.class文件进内存
- 在栈内存为s开辟空间
- 在堆内存为学生对象开辟空间
- 对学生对象的成员变量进行默认初始化
- 对学生对象的成员变量进行显示初始化
- 通过构造方法对学生对象的成员变量赋值
- 学生对象初始化完毕,把对象地址赋给s变量
静态成员的注意点(难点)
- 所属不同
- 静态变量属于类,所以也称为类变量
- 成员变量属于对象,所以也称为实例变量(对象变量)
- 内存中位置不同
- 静态变量存储于方法区的静态区
- 成员变量存储于堆内存
- 内存出现时间不同
- 静态变量随着类的加载而加载,随着类的消失而消失
- 成员变量随着对象的创建而存在,随着对象的消失而消失
- 调用不同
- 静态变量可以通过类名调用,也可以通过对象调用
- 成员变量只能通过对象名调用
创建工具类的小技巧
我们提供一个工具类,让其他类去调用该类的方法,但是我们不希望别人去实例化对象来调用类方法,可以对构造方法private,从而阻止类的实例化。
代码块
局部代码块,局部位置,限定变量的生命周期
public class HelloWorld {
public static void main(String[] args) {
{
int x = 3;// 局部代码块
}
System.out.println(x); //无法访问
}
}
构造代码块,在类中成员位置,用{}括起来的代码。执行过程:每次调用构造方法执行前,都会执行构造代码块。作用:可以把多个构造方法中共同代码放到一起。
class Student{
{
System.out.println("第一个构造代码块");
}
public Student(){ System.out.println("我是构造方法"); }
{
System.out.println("第二个构造代码块");
}
}
public class HelloWorld {
public static void main(String[] args) {
Student s = new Student();
}
}
输出:
第一个构造代码块
第二个构造代码块
我是构造方法
静态代码块,在类中成员位置,用{}括起来,用static修饰。作用:一般是对类的初始化。
class Student{
static {
System.out.println("我是静态代码块");
}
{
System.out.println("我是构造代码块");
}
public Student(){ System.out.println("我是构造方法"); }
}
public class HelloWorld {
public static void main(String[] args) {
Student s1 = new Student();
System.out.println("===========");
Student s2 = new Student();
}
}
输出:
我是静态代码块
我是构造代码块
我是构造方法
===========
我是构造代码块
我是构造方法
注意:各个代码块的执行顺序:静态代码块-》构造代码块-》构造方法;其中静态代码块只执行一次(只要一加载到内存时就执行),构造代码块在每次创建对象的时候都会执行。
class HelloWorld{
static {
System.out.println("我是静态代码块");
}
{
System.out.println("我是构造代码块");
}
public HelloWorld(){ System.out.println("我是构造方法"); }
public static void main(String[] args) {
System.out.println("我是主函数");
}
}
输出
我是静态代码块
我是主函数