Java学习
下载
一般使用Java8或Java11 https://www.oracle.com/cn/java/technologies/downloads/#java8-windows
安装
安装路径不要有空格或中文 https://zhuanlan.zhihu.com/p/387618280
Jdk是什么?
Java development kit java开发工具包
Jdk包括:
Jre( java运行环境)、
一堆java工具(java编译器javac.exe java解释执行器java.exe)、
java基础类库(3600多)常用类150多个
为什么配置环境变量
当前执行程序在当前目录下如果不存在,win10系统会在已有的名为path的环境变量指定的目录中查找
java在线API
https://www.matools.com/api/java8
程序文件说明
Hello.java 源文件 通过javac.exe编译成.class文件
Hello.class 字节码文件 通过java.exe运行在JVM(虚拟机)
public class HelloWorld { public static void main(String []args) { // 固定写法,不可改变 System.out.println("Hello World!"); // Java必须带分号 } }
java在线工具
https://c.runoob.com/compile/10/
数据类型
字符类型
使用单引号,单个字符,精度2个字节(可以放汉字)
本质是整数,输出时输出Unicode码对应的字符 ,可以运算
多个字符用String类(字符串是类-引用类型)
char c1 = 'a'; char c2 = '\t'; // 可以放转义字符 char c3 = '汉'; char c4 = 97; // 字符类型可以存放数字,输出ASCII对应的字符a
ASCII编码表:一个字节,128个字符(实际上一个字节可以表示256字符,ascii只用了128个)
Unicode编码表:兼容ASCII固定大小 2个字节(共65536个字符),字母和汉字都会用2个字节,浪费空间
utf-8编码表:大小可变的编码 字母使用1个字节,汉字使用3个字节
gbk:可以表示汉字,范围广,字母使用1个字节,汉字使用2个字节
gb2312:(可以表示汉字,gb2312<gbk))
big5码:繁体中文,台湾香港
数值类型
~ Java的整数数据类型有固定的范围和字段长度,不受操作系统影响-可移植性
~ Java的整型常量默认为int 申明long后面必需加'l','L'
~ Java的浮点型常量默认为 double型 float型后面必需加‘f'或'F'
~ 表现形式:十进制 5.0f .23 5.12 (必需有小数点) 3d
科学计数法 5.12e2 5.12E-2
~ 浮点数在及其中存放形式:浮点数=符号位+指数位+尾数位(可能丢失,精度损失,小数都是近似值)
~ 浮点数相除后,计算机计算出的精度不正确,如何比较大小:两个数的插值的绝对值非常小
比如 Math.abs(num1-num2) < 0.0000001 就判断是相等的
类型转换
自动类型转换
注意
~ 多种数据类型混合计算时,首先自动将所有数据转换成容量最大的数据类型,再计算
~ 精度大的数据赋值给精度小的会报错
~ (byte,short)和char之间不会自动转换
~ byte short, char 3者可以计算,会先转为int
~ boolean不参与转换,值永远是true或false
~ 自动提升原则:表达式结果的类型自动提升为 操作数中最大的类型
强制类型转换(精度大->精度小)
强转符号只对最近的数值有效 会损失精度或者溢出
int i = (int)1.9 // 1
int x = (int)(8*1.1)
基本数据类型 -> String类
double i = 1.22; String str = i + '';
String -> 基本数据类型 使用 基本数据类型对应的包装类,的相应方法
String str = "123"; byte b = Byte.parseByte(str); short s = Short.parseShort(str); int i = Integer.parseInt(str); long l = Long.parseLong(str); float f = Float.parseFloat(str); double d = Double.parseDouble(str); boolean boo = Boolean.parseBoolean("true");
str.charAt(0); // 字符串转成字符char: 得到第一个字符
运算符
算数运算符
10/3 = 3
关系运算符
逻辑运算符
区别
&&:如果第一个条件为false,则第二个条件不会执行
&:两个条件都要执行
||:如果第一个条件为true,则第二个条件不会执行
|:两个条件都要执行
赋值运算符
基本:=
复合:+= -= *= /=
~ 复合赋值运算符会进行类型转换
byte b = 3; b += 1; // 等价于 b = (byte)(b + 1); b = b + 1; // 会报错
三元运算符
条件表达式 ?表达式1 :表达式2
~表达式1和表达式2要为可以赋值给接收变量的类型(或可以自动类型转换)
运算符优先级
进制
进制转换1
二进制转十进制
从右往左 0b111 = 1 * 20+ 1 * 21 + 1 * 22 = 1+2+4
八进制转十进制
从右往左 0111 = 1 * 80 + 1 * 81+ 1 * 82= 1+8+64
十六进制转十进制
从右往左 0x111 = 1 * 160 + 1 * 161+ 1 * 162= 1+16+256
进制转换2
十进制转二进制
规则:将该数不断除以2,直到商为0为止,然后将每部得到的余数倒过来
十进制转八进制
规则:将该数不断除以8,直到商为0为止,然后将每部得到的余数倒过来
十进制转十六进制
规则:将该数不断除以16,直到商为0为止,然后将每部得到的余数倒过来
进制转换3
二进制转八进制
规则:从右往左,将二进制每3位一组,转成对应的八进制
0b11(3)010(2)101(5) => 0325
二进制十六进制
规则:从右往左,将二进制每4位一组,转成对应的十六进制
0b1101(D)0101(5) => 0xD5
进制转换4
八进制转二进制
规则:从右往左,将八进制每1位,转成对应的3位二进制
02(010)3(011)7(111) => 0b0010011111
十六进制二进制
规则:从右往左,将十六进制每1位,转成对应的4位二进制
02(0010)3(0011)B(1011) => 0b001000111011
位运算
原码,反码,补码:为什么这么设计--为了解决正数负数
程序控制结构
if else
for
while
do while
switch
continue
break
return
public class HelloWorld { public static void main(String []args) { // 输出a-z for(char c1 = 'a'; c1 <= 'z'; c1++) { System.out.println(c1 +" "); } } }
数组
数组:存放多个同一类型的数据,引用类型, 是个对象
数组动态初始化
数据类型 数组名[] = new 数据类型[大小]
double[] list = new double[5]; // 等价于 double list[] = new double[5]; // 先声明和new
list[0] = 1.1; // 再赋值
数组创建后,如果没有赋值,会有默认值
int 0, short 0, byte 0, long 0, float 0.0 double 0.0 char \u000 boolean false String null
数组静态初始化
double[] arr = {1, 3, 5, 4,3, 6.9, 7}; double sun = 0; for (int i = 0; i < arr.length; i++) { sum += arr[i]; }
数组拷贝
数组是引用类型,拷贝时是拷贝地址
int[] arr1 = {1,1,3}; int[] arr2 = new Int[arr1.length]; // 重新开辟空间
数组下标必须在指定范围内,否则报错
数组反转
int arr[] = {11,22,33,44,55,66}; int temp = 0; int len = arr.length; for( int i = 0; i < len/2; i++ ) { temp = arr[len-1-i]; arr[len-1-i] = arr[i]; arr[i] = temp; }
数组排序
1 内部排序:数据量少,在内存中排序(交换式排序法,选择式,插入式)
2 外部排序:数据量多,需要借助外部存储器(合并排序)
冒泡排序
从左到右,相邻元素进行比较。每次比较一轮,就会找到序列中最大的一个或最小的一个。这个数就会从序列的最右边冒出来。
以从小到大排序为例,第一轮比较后,所有数中最大的那个数就会浮到最右边;第二轮比较后,所有数中第二大的那个数就会浮到倒数第二个位置……就这样一轮一轮地比较,最后实现从小到大排序。
int[] arr = {2,4,6,3,5,1}; int temp = 0; int len = arr.length - 1; for (int i = 0; i < len; i++) { for( int j = 0; j < len - i; j++) { if(arr[j] < arr[j+1]){ temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } }
二维数组
动态初始化
int arr[][] = new int[2][3];
int arr[][] = new int[2][]; // 列数可以不确定
静态初始化
int[][] arr = {{1,2,3}, {4,5,6}, {7,8,9}};
类与对象
创建
class Cat { String name; int age; } Cat cat1 = new Cat(); cat1.name = "huahua";
对象内存布局
String类型的属性,存的也是地址指向‘方法区’
对象的属性
访问修饰符:控制属性访问范围 public protected private
属性的类型:基本数据类型,引用数据类型
属性默认值:int 0, short 0, byte 0, float 0.0, double 0.0, char \u0000, boolean false
Java内存结构
栈:一般存放基本数据类型
堆:存放对象(Cat cat, 数组等)
方法区:常量池(常量,比如字符串),类加载信息(属性信息,方法信息)
对象的方法调用机制
成员方法定义
访问修饰符 返回的数据类型 方法名(形参列表) { ... return 返回值 }
成员方法传参机制
基本类型传参:传递的是值(值拷贝),形参的任何改变不影响实参
引用类型传参:传递的是地址,可以通过形参影响实参
递归
方法重载
Java中允许同一个类中,多个同名方法存在,但要求形参列表不一样
1 方法名相同
2 参数(类型,顺序,个数)至少有一个不同
3 参数名和返回类型不要求
可变参数
实参可以为0个或任意多个
实参可以为数组
可变参数的本质就是数组
可变参数可以和普通类型参数一起放形参列表,但必须放最后面
一个形参列表中只能出现一个可变参数
public int sum(String str, int... a) {} // a是数组
作用域
构造方法/构造器constructor
构造器可以重载,是类的一种特殊方法,作用:完成新对象的初始化
class Person { String name; int age; // 默认构造器 public Person() { age = 10; } // 构造器名字和类名一样,没有返回值,也没有void public Person(String pName, int pAge) { name = pName; age = pAge; } } // 当我们new时,系统自动通过构造方法完成对象属性的初始化 Persion p = new Person("lili" , 18);
如果没有定义构造器,系统会自动给类生成一个无参构造器(默认构造器)例如Person() {}
如果定义了构造器,就会覆盖默认构造器,这时无参构造器就不能使用了,除非再定义一下
反编译javap
在jdk/bin 对class文件进行反编译
javap Person.class
对象创建过程*
this
class Person { String name; int age; public Person() { // 访问构造器语法:this(参数列表); 必需放在第一条语句 // 只能在构造器中访问另一个构造器 this("wang", 11); } public Person(String name, int age) { this.name = name; this.age = age; } }
IDEA使用
常用快捷键
查看快捷键设置
模板快捷键,可以自己定义模板
包
本质就是创建不同的文件夹/目录来保存类文件
自定义包
包的命名
常用的包
包使用
推荐需要哪些类就导入哪些
import java.util.Scanner; // 只导入scanner import java.util.*; // 导入util下所有类
访问修饰符*
面向对象的编程
封装(encapsulation)
实现步骤
或者
继承(extends)
继承的特点
继承的本质
super关键字
super好处
this与super比较
方法重写override
注意事项
重载与重写比较