jvm(java virtual machine)根据不同的操作系统有对应的jvm,java编写的程序是在java虚拟机上运行的,对于不同os的用户来说,只需要关心程序怎样在jvm上运行即可,jvm为应用程序提供了统一的一套标准,所以我们无需关注底层,同一套代码可以在jvm的帮助下,在各个不同的os上运行。
2.多线程 3.分布式 4.动态性 5.安全性 二、java适用领域嵌入式、客户端(安卓)、服务器、大数据。
三、开发环境 1.JDKjdk功能:编译运行java、java基础类库(API和函数的集合)、打包项目工程、监控调优。
jdk下载:oracle官网、1018991682群文件、
在cmd中用java -version检测是否安装成功。
2.IDE主流:IDEA
下载:jetbrains官网下载(激活方式:1.学生邮箱2.百度搜idea激活码)
idea回退快捷键是ctrl+z
四、java基础知识 1.helloworld 打开IDEA,新建---注入jdk---不用选取模板---起项目名---右键src文件夹---new---java class---起类名注:libraries下面是很多包
IDEA的联想功能:输入sout之后按enter或者tab键可以直接出来System.out.println();
同理输入psvm可以出现
public static void main(String[] args) {
}
helloworld程序
public class helloworld {
public static void main(String[] args) {
System.out.println("helloworld");
}
}
2.java代码结构
public:访问控制符
class:类关键字,相当于int i当中的int
helloworld:类名(第一个字母大写) ps:包名首字母小写,对象名首字母也小写
ps:驼峰命名法(printEmployeePaychecks();√
print_employee_paychecks();×)
static:关键字,表示静态的
void:方法返回值的类型,void表示无返回值
main:方法名,main函数是java程序的主入口
String[] args:方法的形参,在main函数中特指控制台输入的参数
控制台输入:在运行完一遍helloworld程序后,右上角出现
点击向下的箭头,再点击edit configurations,然后在
输入my boy(注意两个单词之间有空格)
这样的话my和boy相当于两个参数输入到args[]数组当中去,然后运行下方代码
public class helloworld {
public static void main(String[] args) {
System.out.println("helloworld");
for(int i=0;i
点击代码左侧的三角形
运行结果如下
3.必备编程基础
右键src--new--package 新建包 取名l4(第四节),再把刚才的helloworld程序放进到这个包里(拖进去即可),点击refcator,然后点击左下角的Do Refactor。
右键src--new--package 新建包 取名l5,在l5这个包下新建一个类,即右键l5--new--class
package l5;
public class Basics {
int i=3;
long l=4;
float f=3.2F;
double d=4.3;
char c='x';
String s="hello";
boolean b=true;
public static void main(String[] args) {
int arrayA[]={1,2,3};
int []arrayB={2,3,4};
int[] arrayC={3,4,5};
int arrayD[]=new int[100];
int arrayE[];
arrayE=new int[10];
arrayE[0]=3;
System.out.println(arrayE[0]);
}
4.类和对象
对象是类的一个实例,有状态和行为。类是一个模板,它描述一组对象的状态和行为。
右键src新建l6的包,再右键l6新建一个类,类名起为Workman
package l6;
public class Workman {
String name;
int age;
String position;
//以上是状态
void work(){
System.out.println("我正在从事"+position+"的工作");
}
void eat(){
System.out.println("我正在吃饭");
}
//以上是行为
//构造函数的显式声明,如果显式声明构造函数,编译器就不会帮我们产生构造函数
void Workman()
{
System.out.println("我正在构造");
}
}
public static void main(String[] args) {
//输入了一个3,把3通过一个整数构造的方式,变成一个整数,(这样机器就会知道3是一个整数)然后赋给i,
//int i=3;
//参考https://www.cnblogs.com/dearcabbage/p/10603460.html
//int和Integer的区别 1、Integer是int的包装类,int则是java的一种基本数据类型
// 2、Integer变量必须实例化后才能使用,而int变量不需要
// 3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
//int i=3;还可以这么写
Integer i=new Integer(value:3);
//实例化。对象名称一般小写 所以是jack
Workman jack=new Workman();//注意这里使用的是构造函数,即使Workman这个方法没有定义,也可以调用,没有方法体,没有参数。注意构造函数也可以如上面那样显式定义
Workman engineer = new Workman();
jack.position="程序员";
engineer.position = "搬砖工人";
System.out.println("--------");
jack.work();
engineer.work();
}
其实上面这段代码有错误,psvm应该写在类里面的...当时翻了好久
5.java报错类型
1.java: 进行语法分析时已到达文件结尾 原因:缺少一}
2.java: 需要 class、interface、enum 或 record 原因:右下角utf-8转换为GBK,注意reload和convert的区别。。。。然鹅,我上面的那种错误也会这么提示
3.错误: 无法从静态上下文中引用非静态 变量 this 原因:静态方法可以通过所在类直接调用而不需要实例化对象,非静态成员变量则是一个对象的属性。它只有在有实例化对象时才存在的,所以在静态方法中是不可以调用静态变量的!
6.构造函数和this指针 构造函数其中第四条是为了区分构造函数和自定义函数。
package l7;
public class Person {
String name;
Integer age;
Person(){
}
//键盘的alt+insert,笔记本的insert可能跟delete在一起,所以笔记本是alt+fn+insert,选construcor构造器,把name age两个参数都选上
public Person(String name, Integer age) { //自动生成的是带有public修饰符的
this.name = name;
this.age = age;
}
public static void main(String[] args) {
Person person = new Person();
person.name = "jack";
System.out.println(person.name);
}
}
这个代码段中有一个使用小技巧!
this指针- this指代当前实例(当前对象)
- 指代当前类的构造函数
package l7;
public class Person {
String name;
Integer age;
Person(){
}
//键盘的alt+insert,笔记本的insert可能跟delete在一起,所以笔记本是alt+fn+insert,选construcor构造器,把name age两个参数都选上
public Person(String name, Integer age) { //自动生成的是带有public修饰符的
this.name = name;
this.age = age;
}
public static void main(String[] args) {
Person person = new Person();
person.name = "jack";
System.out.println(person.name);
}
}
7.包装类和基本类型数据(211:包装类概述_哔哩哔哩_bilibili)
基本类型数据都存在栈里面,引用类型数据都存在堆里面,栈里面还存这个引用对象的地址。
比如Byte类将基本数据类型byte的值包装在一个对象中,一个Byte类型的对象只包含一个类型为byte的字段,因为此时为引用类型,所以就有一些方法可以使用。//一旦包装之后,数据就放在堆空间中了,栈里面存的是它的引用,也就是说把原来存在栈里面的数据放堆里面了。
如果 int num=1;num.之后没有出现任何可以引用的方法,所以这些基本类型的数据只可以用运算符来对其进行操作。为了给基本类型数据提供更强大的功能,分别为这八个基本数据类型提供了引用类型,包装类默认值是null。integer类提供了多个方法,能在int类型和String类型之间互相转换。
具体参考在线文档-jdk-zh (oschina.net) 搜索jdk api然后找到lang包下的类
Java包装类Java不仅支持上述8种基本数据类型,还为这8种基本数据类型提供了对应的包装类,通过这些包装类,我们就可以将上述基本数据类型当做Java中的类对象来处理了。值得说明的是,Java程序中可以直接操作基本数据类型,但是某些情况下需要将它们看成对象来处理,这些情况下就需要借助于Java API中基本数据类型对应的包装类来处理了。
作用:Java中的基本类型不是面向对象的,它们只是纯粹的数据,除了数值本身的信息之外,基本类型数据不带有其他信息或者可操作方法。这在实际使用中存在很多不足,为了解决这个不足,对每个基本类型都对应了一个引用的类型,称为装箱基本类型。
short → Short、int → Integer、long → Long、char → Character、byte → Byte、float → Float、boolean → Boolean、double → Double
实际上,JAVA中还存在另外一种基本类型void,它也有对应的包装类Void,不过无法直接对它们进行操作。
装箱:根据数据创建对应的包装对象。
Integer i = new Integer(3); Integer j = 4;//jdk1.5 之后可以通过这种方式自动装箱
拆箱:将包装类型转换为基本数据类型。
int index2 = j.intValue(); int index1 = i;//自动拆箱
基本数据类型和包装类型的区别——
1. 包装类是对象,拥有方法和字段,对象的调用都是通过引用对象的地址,基本类型不是;
2. 包装类型是引用的传递,基本类型是值的传递;
3. 声明方式不同,基本数据类型不需要new关键字,而包装类型需要new在堆内存中进行new来分配内存空间;
4. 存储位置不同,基本数据类型直接将值保存在值栈中,而包装类型是把对象放在堆中,然后通过对象的引用来调用他们,因此,包装类的效率会比基本数据类型的效率要低。
5.初始值不同,比如:int的初始值为0、boolean的初始值为false,而包装类型的初始值为null;
6. 使用方式不同,基本数据类型直接赋值使用就好,而包装类型是在集合,比如Collection、Map时会使用。
对于数值类型的基本类型的取值范围,我们无需强制去记忆,因为它们的值都已经以常量的形式定义在对应的包装类中了。
public class PrimitiveTypeTest{
public static void main(String[] args) {
System.out.println("基本类型:byte 二进制位数:" + Byte.SIZE);
System.out.println("包装类:java.lang.Byte");
System.out.println("最小值:Byte.MIN_VALUE=" + Byte.MIN_VALUE);
System.out.println("最大值:Byte.MAX_VALUE=" + Byte.MAX_VALUE + "n");
System.out.println("基本类型:short 二进制位数:" + Short.SIZE);
System.out.println("包装类:java.lang.Short");
System.out.println("最小值:Short.MIN_VALUE=" + Short.MIN_VALUE);
System.out.println("最大值:Short.MAX_VALUE=" + Short.MAX_VALUE + "n");
System.out.println("基本类型:int 二进制位数:" + Integer.SIZE);
System.out.println("包装类:java.lang.Integer");
System.out.println("最小值:Integer.MIN_VALUE=" + Integer.MIN_VALUE);
System.out.println("最大值:Integer.MAX_VALUE=" + Integer.MAX_VALUE + "n");
System.out.println("基本类型:long 二进制位数:" + Long.SIZE);
System.out.println("包装类:java.lang.Long");
System.out.println("最小值:Long.MIN_VALUE=" + Long.MIN_VALUE);
System.out.println("最大值:Long.MAX_VALUE=" + Long.MAX_VALUE + "n");
System.out.println("基本类型:float 二进制位数:" + Float.SIZE);
System.out.println("包装类:java.lang.Float");
System.out.println("最小值:Float.MIN_VALUE=" + Float.MIN_VALUE);
System.out.println("最大值:Float.MAX_VALUE=" + Float.MAX_VALUE + "n");
System.out.println("基本类型:double 二进制位数:" + Double.SIZE);
System.out.println("包装类:java.lang.Double");
System.out.println("最小值:Double.MIN_VALUE=" + Double.MIN_VALUE);
System.out.println("最大值:Double.MAX_VALUE=" + Double.MAX_VALUE + "n");
System.out.println("基本类型:char 二进制位数:" + Character.SIZE);
System.out.println("包装类:java.lang.Character");
// 以数值形式而不是字符形式将Character.MIN_VALUE和Character.MAX_VALUE输出到控制台
System.out.println("最小值:Character.MIN_VALUE=" + (int) Character.MIN_VALUE);
System.out.println("最大值:Character.MAX_VALUE=" + (int) Character.MAX_VALUE);
}
运行结果:
基本类型:byte 二进制位数:8 包装类:java.lang.Byte 最小值:Byte.MIN_VALUE=-128 最大值:Byte.MAX_VALUE=127 基本类型:short 二进制位数:16 包装类:java.lang.Short 最小值:Short.MIN_VALUE=-32768 最大值:Short.MAX_VALUE=32767 基本类型:int 二进制位数:32 包装类:java.lang.Integer 最小值:Integer.MIN_VALUE=-2147483648 最大值:Integer.MAX_VALUE=2147483647 基本类型:long 二进制位数:64 包装类:java.lang.Long 最小值:Long.MIN_VALUE=-9223372036854775808 最大值:Long.MAX_VALUE=9223372036854775807 基本类型:float 二进制位数:32 包装类:java.lang.Float 最小值:Float.MIN_VALUE=1.4E-45 最大值:Float.MAX_VALUE=3.4028235E38 基本类型:double 二进制位数:64 包装类:java.lang.Double 最小值:Double.MIN_VALUE=4.9E-324 最大值:Double.MAX_VALUE=1.7976931348623157E308 基本类型:char 二进制位数:16 包装类:java.lang.Character 最小值:Character.MIN_VALUE=0 最大值:Character.MAX_VALUE=65535
Float和Double的最小值和最大值都是以科学记数法的形式输出的,结尾的“E+数字”表示E之前的数字要乘以10的多少次方。
需要补充
BigInteger BigDecimal可以表示超出Integer、Decimal范围的数据。
String为了方便才可以直接赋值,其实原本要new一下。 String定义的变量是指向堆空间的内容,
字符串常量池 String s1="abc"; 放在字符串常量池 再定义String s3="abc",就不开空间了,直接指向一个位置
String s2= new String(“abc”);放在堆区。。
s1==s2 false s1==s3 true
StringBuilder StringBuffer(多线程) 一些string操作
toString
8.java虚拟机内存管理(待解决 ! 参考Java对象内存管理 【最接地气的讲解】_哔哩哔哩_bilibili)Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同数据区域。这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。
main方法单独创建线程 、栈作为线程的空间
程序计数器
程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复等基础功能都需要依赖这个计数器来完成。
如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址,如果正在执行的是Native方法,这个计数器值则为空。此内存区域是唯一个在Java虚拟机规范中没有规定任何OurOfMemoryError情况的区域。
虚拟机栈
与程序计数器一样,Java虚拟机栈也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stack frame)用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(Object reference)和字节码指令地址(returnAddress类型)。
在Java虚拟机规范中,对于此区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。
对于32位的jvm,默认大小为256kb, 而64位的jvm, 默认大小为512kb,可以通过-Xss设置虚拟机栈的最大值。不过如果设置过大,会影响到可创建的线程数量。
方法区
方法区与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据。
根据Java虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。
本地方法栈
本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用非常类似,区别在于虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则是为虚拟机使用到的Native方法服务。
Java堆
Java堆(java heap)是Java虚拟机所管理的内存中最大的一块,它是被所有线程共享的一块内存区域,在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
Java堆是垃圾收集管理的主要区域,因此很多时候也被称为 "GC" 堆。
根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的。(通过-Xmx和-Xms控制)如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
9.静态变量和静态方法参考Java static关键字(静态变量和静态方法) (biancheng.net)
10.一些常用的thingScanner类--next() nextLine()的使用 参考Java Scanner 类 | 菜鸟教程 (runoob.com)
11.继承、多态


