Java基础
注意:长篇警告!!目前本笔记7w+字,且图片没能上传成功(懒得搞了)如果觉得有用可以私信我。本笔记为个人学习过程中记录,所学课程均来自网络公开课,笔记内容如有错误欢迎指正。本笔记仅供个人学习使用,转载请联系私信本人
前言:
- 不同版本
javaSE 桌面
javaME 移动
javaEE 服务器
- 跨平台
jvm使得java可以跨平台,我们编写的java程序都是编程jvm字节码在jvm上执行,不同的操作系统负责实现本操作系统下的jvm
- 特性
简单,面向对象,可移植性,高性能,分布式,动态性,多线程,安全性,健壮性
JDK Java Development Kit 包括jre和jvm还有一些他们没有的东西
JRE Java Runtime Environment 除了jvm还有一些其他运行需要的东西(只需要运行java程序只需要安装jre即可)
jvm Hava Virtual Machine
- java程序运行机制
源文件首先编译成字节码(.class)之后再通过类加载器,字节码校验器 解释器才能运行
一个java文件中只有一个public类,可以有多个class
public class Outer{
}
class test{
public static void main(String[] args){
//这里写Outer类的测试
}
}
文章目录
- Java基础
-
- IDEA快捷键
- 第一章 (基础)
- 第二章(常用类,集合框架,Io)
- 第三章 集合框架
- 第四章 文件和IO流
- 第五章 多线程&JUC
- 第六章 注解(Annotation)和反射
- 第七章 JVM
- 第七章 JVM
IDEA快捷键
psvm //自动生成main函数
sout //自动生成输出
重写方法 alt+insert
选中代码 CTRL+alt+t 抛出异常
alt+7 列出来类的方法大纲
ctrl+f12 类的结构
第一章 (基础)
1.1基本数据类型/变量
- 基本数据类型 (和其他语言雷士)
- byte 1字节
- short 2 byte
- int 4byte
- long 8byte
- float 4byte
- doublt 8byte
- char 2byte
- boolean 1bit
- 引用数据类型 (类 接口 数组)
1.1.1类型定义
// 【1】 基本数据类型
int num=0;
short num3=30;
long num4=20L; //add L
float num5=123.3F; //add F
double num6=1.123;
char name='A';
String name="啊士大夫看见"; //String is not a key word,but a class
Integer name =123124; //Integer is not a key word,but a class
// 【2】 进制 二进制0b 八进制0 十六进制0x
int i=10;
int i2=010;
int i3=0x10l;
// 【3】 浮点数 舍入误差,最好不要用浮点数进行比较
// 【4】 字符扩展 Unicode 2字节编码 0-65536 97-a U0000-UFFFF
char cs ='\u0061'; //unicode编码
// 【5】 String类
String a=new String("hello");
String b = new String("hello"); //a!=b
String c="hello";
String d="hello"; //c==d
1.1.2类型转换
// 【1】 强制类型转换的时候避免内存溢出 (高到低)
int i=128;
byte b=(int)i;
// 【2】 自动转换 (低到高)
int i =123;
double b=i;
// 【3】 计算之前如果有溢出,可以先转换再计算
long total = 1000000000*(long)20;
1.1.3变量 常量 作用域
final 表示常量
static 类变量可以在类的方法中直接使用
修饰符不存在先后顺序
1.2运算符
// 【1】 Math类,java中没有^幂运算,需要用到Math类的pow方法
// 【2】 条件运算符 ?:
int a = x?a:b; //如果x为真a=a,否则a=b
1.3用户交互
// 【1】 接受用户输入
Scanner scanner = new Scanner(System.in);
//判断用户是否输入
if(scanner.hasNext()){
String str= scanner.next(); //空格隔开 nextLine可以接受一行以为回车为结束符
System.out.println(str);
}
scanner.close();
1.4程序结构
//# 1 switch
switch(expression){
case value:
//
break;
case value:
//
break;
default:
//
}
//# 2 增强for循环
for(int x:numbers){
//numbers是可遍历数据类型,
}
1.5方法
java是值传递,不是引用传递
1.5.1可变参数
// 【1】 只可以指定一个可变参数,必须在普通参数之后
public void test(int... i){
//【可变长的参数,封装到一个对象,本质就是一个数组,通过数组下表来找到不同的值】
System.out.println(i[0]);
}
1.6数组
数组的长度在创建后是不变的
数组是一个对象
// 【1】 数组的属性
num.length
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r0hIPok6-1681980768116)(…/Asset/image-20230413163002023-16816270541451.png)]
1.6.1数组的声名和创建
int[] nums; //定义
nums=new int[10]; //使用数组,可以存放10个int类型数字
1.6.2三种初始化
// 【1】 静态初始化
int[] a={
1,2,3,4,5}
Man[] manx={
new Man(1),new Man(2)}
// 【2】 动态初始化
int[] nums=new int[10]; //创建数组后,通过下标来赋值
nums[0]=1;
// 【3】 默认初始化
int[] nums=new int[10]; //这里面有默认的值0
1.6.3数组工具类Arrays
// 【1】 打印数组
int[] a={
1,2,3,4,5};
Arrays.toString(a);
// 【2】 数组填充
int[] a={
1,2,3,4,5}
Arrays.fill(a,0); //[0,0,0,0,0]
1.7面向对象
栈是一些方法和引用
堆里面才是实际的对象,其中堆里面有个特殊的方法区,存放的是类的方法,类加载的时候加载到这里,同时一些静态方法也在这里,随这类一块加载。
类的具体对象放在堆中,对象属性修改,实际上是把创建该对象的类里面的一些值赋值给该对象。
一个类只有一个Class对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aUDt7Ilc-1681980768117)(…/Asset/image-20230413165349580-16816270566443.png)]
1.7.1继承
idea中ctrl+h查看当前类的继承关系
java中只有单继承,没有多继承
java中final修饰的类无法被继承
- this指代自己,super指代直接继承的父类方法,super只能出现在子类的方法中
- 私有无法继承
- 调用父类的构造器,调用自己的构造器,只能放在第一行
- 继承的无参构造会自动调用父类的无参构造
- 有参构造写好后,自动销毁无参构造,并且该类的子类也同样无法写无参构造。因此写了有参构造后一定要手动添加无参构造方法
- this()本地无参构造 super()父类无参构造
重写方法
- 方法名相同
- 参数列表必须相同
- 修饰符,范围可以扩大但不能缩小
- 抛出异常,范围可以缩小,不能扩大(父类没有抛出异常,子类就不可以抛出异常)
//【1】方法重写(静态方法) 和重载不太一样,和属性无关
A a=new A();
a.test(); //子类的方法
B b=new A(); //父类的引用指向子类,
b.test(); //父类的方法【方法的调用只和该引用的类型有关,引用
//【2】方法重写(非静态方法) 谁的实例调谁的方法
1.7.2多态
动态编译,能执行的方法看引用的类型,对象的实例时确定的,时右面new的类型
- 多态是方法的多态,属性没有多态
- 父类和子类,有联系,否则类形转换异常
- 继承关系,方法重写,到底执行谁只有在运行的过程中才能判定(因为可以类型转换)
1.7.3 instanceof 和类型转换
- instanceof
instanceof 判断一个对象时什么类型
x instanceof y //x是y的子类,结果是true
Object object = new Student();
object instanceof Student;//true
object instanceof Person;//true
object instanceof Teacher;//false
- 类型转换
子类转换为父类可能会丢失一些方法。
父类转换为子类,强制转换
1.7.4抽象类和接口
- 抽象类
- 有抽象方法的类就是抽象类,抽象方法用abstract修饰。类里面也可以有普通方法
- 不能new,只能靠子类来实现,new子类…可以看作是个框架。
- 抽象类还是各类,只能用extends来继承,只能单继承
public abstract class Action{
public void run(){
}
}
public class example extends Action{
public void run(){
System.out.println("run");
}
}
- 接口
- 只有规范,没有普通方法,实现约束和实现分离
- 不用class用interface
- 接口不能被实例化,接口中没有构造方法
public interface UserService{
//默认都是public abstract
public abstract void run();
void run();//和上面的定义相同
void add(String str);
}
public class UserServiceImpl implements UserService{
//这里面需要重写接口的所有方法
}
1.7.5内部类
- 成员内部类
public class Outer{
private int id;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
public void getId(){
System.out.println(id);//内部类可以操作外部类的私有属性
}
}
public static class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
public void getId(){
System.out.println(id);//【这里会报错,因为类是static但是属性不是static属性】
}
}
}
Outer outer=new Outer();
Outer.Inner inner = outer.new Inner();// 通过外部类来new内部类
- 局部内部类,在方法中的类,只局限于方法内部
- 静态内部类
public class Test{
private name='123';
static class inner{
private age=20;
public void fun(){
sout(age,Test.name)
}
}
}
Test.inner = new Test.inner();//可以直接new
- 匿名内部类
interface UserService{
void hello();
}
public class Test{
public static void main(String[] args){
//下列下发就是匿名内部类的形式
new Uservice(){
public void hello(){
System.out.println("实现接口的方法");
}
}.hello();
//上述写法等价于
calss User implements UserService{
public void hello(){
System.out.println("实现接口的方法");
}
}
User user= new User();
user.hello();
}
}
1.8static关键字
-
static属性属于类,用类名访问,被所有对象共享
-
static方法属于类,类加载的时候就加载了,不需要实例,直接用类名来调用
-
static方法里面只能调用static修饰的方法
-
静态代码块,类加载额时候只执行一次
public class Person{
static{
System.out.println("静态代码块")//最先执行,只执行一次
}
{
System.out.println("匿名代码块")//第二执行,赋初始值,可以多次执行
}
public Person(){
System.out.println("构造方法")//最后执行
}
}
1.9异常
- 检查性异常:用户错误操作引起的异常
- 运行时异常
- 错误ERROR 大多数都是虚拟机抛出,Error后虚拟机会选择终止
异常处理框架:所有的异常当作一个对象处理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KhYM0ePc-1681980768118)(…/Asset/image-20230414150322748-16816270763905.png)]
异常处理:
- jvm处理及默认处理(打印异常信息到控制台,程序终止)
- 抛出异常程序处理
//【1】初识异常 选中代码块后 按ctrl+alt+t
public class Test {
public static void main(String[] args) {
int a=1;
int b=0;
try {
//监控区域
System.out.println(a/b);
}catch (Exception e){
//里面是需要捕获的异常类型
System.out.println("程序出现异常");
e.printStackTrace();//打印错误信息
}catch(Throwable t){
System.out.println("【==异常可以多次catch,注意小的异常要先写==】");
}finally {
System.out.println("善后工作");
}
try{
new Test().test(1,0);
}catch(Exception e){
e.printStackTrace();
}
}
public void test(int a,int b){
if(b==0){
throw new Exception();//抛出异常,一般在方法中使用,本方法不处理,交给调用改方法的角色去处理
}
System.out.println(a/b);
}
}
//【2】自定义异常
public class MyException extends Exception{
//传递数字,如果数字大于10抛出异常
private int detail;
public MyException(int a){
this.detail=a;
}
//异常打印信息
@Override
public String toString() {
return "MyException{" +
"detail=" + detail +
'}';
}
}
public class Test {
static void test(int a) throws MyException{
if(a>10){
throw new MyException(a); //抛出异常,不在这里处理
}
System.out.println("ok");
}
public static void main(String[] args) {
try {
test(11);
} catch (MyException e) {
System.out.println("MyException=>"+e); //这里的e就是自定义异常的tostring方法的返回值
}
}
}
1.10Stream()流
先学完集合框架后再来看
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SWaVzvIc-1681980768118)(…/Asset/image-20230417155347508.png)]
使用步骤:
- 得到Stream流
- 利用中间方法过滤
- 利用终结方法输出
1.10.1 获取Stream流
注意:双列集合只能通过key获取set集合后,再利用单列集合来操作。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7QOwW82v-1681980768118)(…/Asset/image-20230417155451487.png)]
// 【1】 单列集合获取Steam
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"123","231234","!312423","12344","1234","1234324","3253254");
Stream<String> stream1 = list.stream(); //获取集合的流水线,然后放到流水线上
// 【2】 双列集合获取Stream 根据key
HashMap<String, String> hm = new HashMap<>();
hm.put("123","321");
hm.put("231","432");
Stream<String> stream2 = hm.keySet().stream();
// 【3】 双列集合获取Stream 根据Entries
HashMap<String, String> hm = new HashMap<>();
hm.put("123","321");
hm.put("231","432");
hm.entrySet().stream().forEach(s-> System.out.println(s));
// 【4】 数组获取Stream 【利用arrays来获取】
int[] arr={
1,2,3,4,5,6,7};
Arrays.stream(arr).forEach(s -> System.out.println(s)); //【无论是引用数据类型还是自定义数据类型的数组都可以用这个方法】
// 【5】 凌乱的一堆数据(同类型) 【利用Steam.of方法】
Stream.of(1,2,3,4,6).forEach(S-> System.out.println(S));//
1.10.2中间方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MmLlIHnP-1681980768118)(…/Asset/image-20230417160444234.png)]
// 【1】 过滤
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"123","231234","!312423","12344","1234","1234324","3253254");
//注意流只能使用依次,建议中间方法和终结方法利用链式编程
list.stream()
.filter(s -> s.startsWith("1"))
.forEach(s -> System.out.println(s));
// 【2】 limit获取前面3个元素 skip写法和limit类似
list.stream()
.limit(3)
.forEach(s -> System.out.println(s));
// 【3】 distinct 去重
list.stream()
.distinct()
.forEach(s -> System.out.println(s));
// 【4】 concat合并
Stream.concat(list1.stream(),list2.stream()).forEach(s->sout(s));
// 【5】 map类型转换 【String->int】
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"张三-3","李四-4","王五-23","天六-44","赵七-4","阿道夫-24","的萨芬-3254");
list.stream()
.map(s-> Integer.parseInt(s.split("-")[1]))
.forEach(s-> System.out.println(s));
1.10.3 终结方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S8SYOV9K-1681980768119)(…/Asset/image-20230417162100746.png)]
// 【1】 收集数据 toArray()
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"张三-3","李四-4","王五-23","天六-44","赵七-4","阿道夫-24","的萨芬-3254");
//String表示要转化为String数组,value表示流里面的数据个数
String[] strr = list.stream()
.map(s -> s.split("-")[1])
.toArray(value -> new String[value]);
System.out.println(Arrays.toString(strr)); //【数组的输出用Arrays里的toString方法】
// 【2】 收集到集合中 collect
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"张三-3","李四-4","王五-23","天六-44","赵七-4","阿道夫-24","的萨芬-3254");
//String表示要转化为String数组,value表示流里面的数据个数
List<String> collect = list.stream()
.map(s -> s.split("-")[1])
.collect(Collectors.toList()); //【collector.toList()创建list集合,同理toSet会帮我们创建一个hashSet集合并把数据放到集合里面】
System.out.println(collect);
// 【3】收集到Map中 【注意:键不能重复】
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"张三-3","李四-4","王五-23","天六-44","赵七-4","阿道夫-24","的萨芬-3254");
Map<String, Integer> collect = list.stream()
//toMap中有两个参数,一个是键的规则,一个是值的规则
//Function<当前流的类型,最终键或值的类型>
.collect(Collectors.toMap(new Function<String, String>() {
@Override
public String apply(String s) {
return s.split("-")[0];
}
}, new Function<