Java基础

常识

java三大平台:JavaSE(基础)、JavaME(小型)、JavaEE(老大)

JVM(Java Virtual Machine),Java虚拟机

JRE(Java Runtime Environment),Java运行环境

JDK(Java Development Kit)称为Java开发工具

技巧

所有的技术都是为了解决问题出现的

创建包不能以数字开头可以用  a01 a02.

右键上方的.java文件   向右拆分可以同时看两个代码,比较方便

相对路径:要从项目名称开始

生成随机数

//生成随机数
Random r=new Random();
int number=r.nextInt(10);//0-9
System.out.println(number);

 占位符%s

//占位符
System.out.printf("%s你好啊%s","张三","李四");

 字符'1'-'0'就是数字1

System.out.print(arr[str1.charAt(i)-'0']);

 loop:while break loop; 可以指定跳出哪一个循环

基础

数据类型

  • 基本数据类型

  • 引用数据类型

四类八种

注意!后缀

//4.定义long类型的变量
long d = 123456789123456789L;
System.out.println(d);

//5.定义float类型的变量
float e = 10.1F;
System.out.println(e);

 当long也存不下的时候用 BigInteger

在使用float或者double类型的数据在进行数学运算的时候,很有可能会产生精度丢失问题

解决方法:BigDecimal

命名规则

小驼峰:变量名、方法名

大驼峰:类名

全小写:包名

ACSCII码表

权限修饰符

编写代码时,如果没有特殊的考虑,建议这样使用权限:

  • 成员变量使用private ,隐藏细节。

  • 构造方法使用public ,方便创建对象。

  • 成员方法使用public ,方便调用方法。

面向对象

对象内存图

成员方法调用过程

标准对象创建要求

ptg:下载ptg插件  右键Ptg To JavaBean 可一键生成标准JavaBean

后期可以用Lombok注解简化代码。

快捷键

alt+insert:插入一些构建类的常用方法

鼠标滚轮竖着选数字,能全部一起修改  或者 alt+左键

ctrl+shift+u:把字符串全部变大写   在写常量(全部大写)的时候用到

this:区分局部变量和成员变量   允许重名 就近原则

ctrl+alt+m:创建方法(method)

ctrl+D:复制上一行

psvm  sout fori:快捷生成代码

格式化代码:Ctrl+Alt+L

ctrl+alt+左键:回到刚刚看的代码

ctrl+alt+v:自动生成左边的变量名

ctrl+alt+t:选择用什么包围

shift+alt+f10:编译代码

ctrl+o:查看可重写的方法

alt+insert:可以重写equall和hashcode方法

局部注释:ctrl+shift+/

ctrl+H:按住一个接口之后可以查看所有实现这个接口的类

创建测试类:alt+enter

ctrl+shif+end:全选光标后面的文字   再按住shift不放可以去掉尾部

static变量

能共享就用,如老师名字    被该类所有的对象共享  

static的注意事项:

静态方法中,只能访问静态

非静态方法可以访问所有

静态方法中没有this关键字

因为类只有一个,所以静态成员变量在内存区域中也只存在一份。所有的对象都可以共享这个变量

工具类

类名一般以Util结尾

public class ArrayUtil {

    private ArrayUtil(){
    }
    public static String printArray(int[] arr){
        StringBuilder sb=new StringBuilder();
        sb.append('[');
        for (int i = 0; i < arr.length; i++) {
            if (i==arr.length-1){
                sb.append(arr[i]);
            }else {
                sb.append(arr[i]).append(',');
            }
        }
        sb.append(']');
        return sb.toString();
    }

    public static double getAverage(double[] arr){
        double sum=0;
        for (double v : arr) {
            sum += v;
        }
        return sum/arr.length;
    }
}

//
public class TestDemo {
    public static void main(String[] args) {
        int[] arr1={10,20,50,34,100};
        String str=ArrayUtil.printArray(arr1);
        System.out.println(str);

        double[] arr2={1.5,3.7,4.9,5.8,6.6};
        double avg=ArrayUtil.getAverage(arr2);
        System.out.println(avg);
    }

}

main方法

封装

对象代表什么,就得封装对应的数据,并提供数据对应的行为

继承

super代表的是父类对象的引用,this代表的是当前对象的引用

当类与类之间,存在共同(相同)的内容,并满足子类是父类的一种就能用。

构造方法:子类、父类名字不一样,继承不了。

成员变量:可以继承,不能直接使用  得用get set

成员变量的访问特点:就近原则     有this访问本类的成员变量  super父类

重写 

当父类的方法不满足子类需求   @Override

多态 

多态: 是指同一行为,具有多个不同表现形式。

例子:Cat和Dog都是动物,都是吃这一行为,但是出现的效果(表现形式)是不一样的。

父类类型 对象名称=new 子类对象

使用父类类型作为参数,可以接受所有子类对象  register(Person p)

口诀:

解释:

原因:

举例来说:如果 Dog 类继承了 Animal 类,并且 Animal 类中有一个 makeSound() 方法,而 Dog 类中重写了这个方法,那么通过 a 引用变量调用 makeSound() 方法时,将会调用 Dog 类中的 makeSound() 方法,而不是 Animal 类中的。 

多态的弊端:不能调用子类的特有功能    因为编译看左边,父类中没有子类的特有方法,所以就报错   解决方法:强制类型转换

instanceof

作用是测试它左边的对象是否是它右边的类的实例

场景:当我在看别人的代码时,不知道要强转成什么类型

常量final

静态代码块

用于数据初始化

匿名内部类

作用:

如果我们希望定义一个只要使用一次的类,就可考虑使用匿名内部类。匿名内部类的本质作用

是为了简化代码

格式

new 父类名或者接口名(){
    // 方法重写
    @Override 
    public void method() {
        // 执行语句
    }
};

//实现
interface Swim {
    public abstract void swimming();
}

public class Demo07 {
    public static void main(String[] args) {
        // 使用匿名内部类
		new Swim() {
			@Override
			public void swimming() {
				System.out.println("自由泳...");
			}
		}.swimming();
    }
}

抽象类

强制子类必须按照父类定义的格式来重写

是什么:父类只需要提供一个没有方法体的定义即可,具体实现交给子类自己去实现。

抽象类存在的意义是为了被子类继承。

例子

// 父类,抽象类
abstract class Employee {
	private String id;
	private String name;
	private double salary;
	
	public Employee() {
	}
	
	public Employee(String id, String name, double salary) {
		this.id = id;
		this.name = name;
		this.salary = salary;
	}
	
	// 抽象方法
	// 抽象方法必须要放在抽象类中
	abstract public void work();
}

// 定义一个子类继承抽象类
class Manager extends Employee {
	public Manager() {
	}
	public Manager(String id, String name, double salary) {
		super(id, name, salary);
	}
	// 2.重写父类的抽象方法
	@Override
	public void work() {
		System.out.println("管理其他人");
	}
}

// 定义一个子类继承抽象类
class Cook extends Employee {
	public Cook() {
	}
	public Cook(String id, String name, double salary) {
		super(id, name, salary);
	}
	@Override
	public void work() {
		System.out.println("厨师炒菜多加点盐...");
	}
}

// 测试类
public class Demo10 {
	public static void main(String[] args) {
		// 创建抽象类,抽象类不能创建对象
		// 假设抽象类让我们创建对象,里面的抽象方法没有方法体,无法执行.所以不让我们创建对象
//		Employee e = new Employee();
//		e.work();
		
		// 3.创建子类
		Manager m = new Manager();
		m.work();
		
		Cook c = new Cook("ap002", "库克", 1);
		c.work();
	}
}

接口

接口是更加彻底的抽象,接口中全部是抽象方法。

定义一种规则,使得代码统一

public interface SportMan {
    void run(); // 抽象方法,跑步。
    void law(); // 抽象方法,遵守法律。
    String compittion(String project);  // 抽象方法,比赛。
}

设计模式

就是解决问题的各种套路

字符串

自动生成左边    输入sc.next()  按alt+enter

字符串的比较

==号的作用
  • 比较基本数据类型:比较的是具体的值

  • 比较引用数据类型:比较的是对象地址值

StringBuilder

StringBuilder 可以看成是一个容器,创建之后里面的内容是可变的

作用:拼接字符串和反转字符串等

集合

泛型

  • 泛型的使用

    用于约束集合中存储元素的数据类型(像一个看门老大爷,符合才能进来)

  • 只支持引用数据类型

  • 泛型类、泛型方法、泛型接口

  • 泛型不具备继承性,数据数据可以继承

通配符  ?

ArrayList常用方法

Collections类是Java中针对集合类的一个工具类,其中提供一系列静态方法:

sort、reverse、fill等

数组的长度固定,集合的长度可变

ArrayList<String> list=new ArrayList<>();

Collection 

set集合不能用普通for来遍历

遍历方式:

迭代器

增强for

lambda表达式

双列集合:Map

所有的单列集合(List,Set)和数组才能用增强for进行遍历。

List

List特有方法介绍

方法名描述
void add(int index,E element)在此集合中的指定位置插入指定的元素
E remove(int index)删除指定索引处的元素,返回被删除的元素
E set(int index,E element)修改指定索引处的元素,返回被修改的元素
E get(int index)返回指定索引处的元素

ArrayList

底层是数组结构实现,查询快、增删慢

扩容时机一:

  1. 当存满时候,会创建一个新的数组,新数组的长度,是原来的1.5倍,也就是长度为15.再把所有的元素,全拷贝到新数组中。如果继续添加数据,这个长度为15的数组也满了,那么下次还会继续扩容,还是1.5倍。

扩容时机二:

  1. 一次性添加多个数据,扩容1.5倍不够,怎么办呀?

    如果一次添加多个元素,1.5倍放不下,那么新创建数组的长度以实际为准。

举个例子: 在一开始,如果默认的长度为10的数组已经装满了,在装满的情况下,我一次性要添加100个数据很显然,10扩容1.5倍,变成15,还是不够,

怎么办?

此时新数组的长度,就以实际情况为准,就是110

LinkedList

底层是双向链表结构实现,查询慢、增删快

核心步骤如下:

  1. 刚开始创建的时候,底层创建了两个变量:一个记录头结点first,一个记录尾结点last,默认为null

  2. 添加第一个元素时,底层创建一个结点对象,first和last都记录这个结点的地址值

  3. 添加第二个元素时,底层创建一个结点对象,第一个结点会记录第二个结点的地址值,last会记录新结点的地址值Set

Set

  • 不可以存储重复元素

  • 没有索引,不能使用普通for循环遍历

HashSet

哈希表结构【理解】

  • JDK1.8以后

    • 节点个数少于等于8个

      数组 + 链表

    • 节点个数多于8个

      数组 + 红黑树

hashCode:比较哈希值

equals:比较属性值

  • 总结

    HashSet集合存储自定义类型元素,要想实现元素的唯一,要求必须重写hashCode方法和equals方法

LinkedHashSet

TreeSet

  • 自然排序、比较器排序   两种比较方式小结

    • 自然排序: 自定义类实现Comparable接口,重写compareTo方法,根据返回值进行排序

    • 比较器排序: 创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序

    • 在使用的时候,默认使用自然排序,当自然排序不满足现在的需求时,必须使用比较器排序

使用场景

Map

  • Map集合的特点

    • 双列集合,一个键对应一个值(Entry对象)

    • 键不可以重复,值可以重复

方法介绍

方法名说明
V put(K key,V value)添加元素
V remove(Object key)根据键删除键值对元素
void clear()移除所有的键值对元素
boolean containsKey(Object key)判断集合是否包含指定的键
boolean containsValue(Object value)判断集合是否包含指定的值
boolean isEmpty()判断集合是否为空
int size()集合的长度,也就是集合中键值对的个数

put注意: 

Map集合的获取功能 方法介绍:

方法名说明
V get(Object key)根据键获取值
Set<K> keySet()获取所有键的集合
Collection<V> values()获取所有值的集合
Set<Map.Entry<K,V>> entrySet()获取所有键值对对象的集合

1.键找值

  • 获取所有键的集合。用keySet()方法实现

//获取所有键的集合。用keySet()方法实现
Set<String> keySet = map.keySet();
//遍历键的集合,获取到每一个键。用增强for实现
for (String key : keySet) {
    //根据键去找值。用get(Object key)方法实现
    String value = map.get(key);
    System.out.println(key + "," + value);
}

2.键值对

//获取所有键值对对象的集合
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        //遍历键值对对象的集合,得到每一个键值对对象
        for (Map.Entry<String, String> me : entrySet) {
            //根据键值对对象获取键和值
            String key = me.getKey();
            String value = me.getValue();
            System.out.println(key + "," + value);
        }

3.Lambda表达式

 HashMap

  • HashMap底层是哈希表结构的

  • 依赖hashCode方法和equals方法保证键的唯一

  • 如果键要存储的是自定义对象,需要重写hashCode和equals方法

LinkHashMap

TreeMap

可变参数 ... 

  public class ChangeArgs {
    public static void main(String[] args) {
        int sum = getSum(6, 7, 2, 12, 2121);
        System.out.println(sum);
    }
    
    public static int getSum(int... arr) {
   		int sum = 0;
   	     for (int a : arr) {
         sum += a;
        }
   		 return sum;
    }
}

注意:

1.一个方法只能有一个可变参数

2.如果方法中有多个参数,可变参数要放到最后

Collections

 集合工具类

java.utils.Collections是集合工具类,用来对集合进行操作。

常用方法如下:

  • 排序

void reverse(List list)//反转
void shuffle(List list)//随机排序
void sort(List list)//按自然排序的升序排序
void swap(List list, int i , int j)//交换两个索引位置的元素
  • 查找、替换

int binarySearch(List list, Object key)//对List进行二分查找,返回索引,注意List必须是有序的
int max(Collection coll)//根据元素的自然顺序,返回最大的元素。 
int max(Collection coll, Comparator c)//根据定制排序,返回最大元素
void fill(List list, Object obj)//用指定的元素代替指定list中的所有元素
int frequency(Collection c, Object o)//统计元素出现次数
int indexOfSubList(List list, List target)//统计target在list中第一次出现的索引
boolean replaceAll(List list, Object oldVal, Object newVal)//用新元素替换旧元素

排序

不可变集合

.of

什么东西:不想让别人修改集合中的内容

List.of()Set.of()Map.of() 和 Map.ofEntries()等工厂方法来创建不可变集合

数组

Arrays类

JDK提供的java.util.Arrays类,包含了常用的数组操作,方便我们日常开发。

Arrays类包含了:排序、查找、填充、打印内容等常见的操作。

常见操作:

1、Arrays.toString()打印数组

2、Arrays.equals(int[] a, int[] a2)比较两个数组是否相同

3、Arrays.copyOf(int[] original, int newLength)复制指定的数组 ---效率低,会重新开辟新的数组空间original - 要复制的数组;newLength - 要返回的副本的长度  左闭右开

4、Arrays.fill(int[] a, int val)/Arrays.fill(int[] a, int fromIndex, int toIndex, int val)填充数组

5、Arrays.sort(int[] a);对数组进行升序排序

6、Arrays.binarySearch(int[] a, int key)二分法查找  有序升序

 该方法是将数组转化成List集合的方法。

 List<String> list = Arrays.asList("a","b","c");

用此方法得到的List的长度是不可改变的

API

Java.lang.System类Java.lang.System 类 (w3ccoo.com)

exit:停止虚拟机

currentTimeMills:获取当前时间的毫秒值

arraycopy:拷贝数组     参数(数据源,从数据源的第几个开始,拷贝到哪,目的地的索引,个数)

正则表达式

下载一个插件any-rule  右键就会有模板

忽略大小写

String str="Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11," +
                "因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
        Pattern p=Pattern.compile("Java\\d{0,2}");
        Matcher m=p.matcher(str);
        while (m.find()){
            String s=m.group();
            System.out.println(s);
        }

爬身份证号码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexDemo7 {
    public static void main(String[] args) throws IOException {
        /* 扩展需求2:
            把连接:https://m.sengzan.com/jiaoyu/29104.html?ivk sa=1025883i
            中所有的身份证号码都爬取出来。
        */

        //创建一个URL对象
        URL url = new URL("https://m.sengzan.com/jiaoyu/29104.html?ivk sa=1025883i");
        //连接上这个网址
        //细节:保证网络是畅通
        URLConnection conn = url.openConnection();//创建一个对象去读取网络中的数据
        BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String line;
        //获取正则表达式的对象pattern
        String regex = "[1-9]\\d{17}";
        Pattern pattern = Pattern.compile(regex);//在读取的时候每次读一整行
        while ((line = br.readLine()) != null) {
            //拿着文本匹配器的对象matcher按照pattern的规则去读取当前的这一行信息
            Matcher matcher = pattern.matcher(line);
            while (matcher.find()) {
                System.out.println(matcher.group());
            }
        }
        br.close();
    }
}

 

时间

data类

SimpleDateFormat类

Calendar类

判断闰年:

包装类

作用:很多情况,会创建对象使用,因为对象可以做更多的功能 ,如果想要我们的基本类型像对象一样操作,就可以使用基本类型对应的包装类

public static int parseInt(String s):将字符串参数转换为对应的int基本类型  

除了Character类之外,其他所有包装类都具有parseXxx静态方法可以将字符串参数转换为对应的基本类型

基本类型与对应的包装类对象之间,来回转换的过程称为”装箱“与”拆箱“:

  • 装箱:从基本类型转换为对应的包装类对象。String s2 = String.valueOf(number)

  • 拆箱:从包装类对象转换为对应的基本类型。int y = Integer.parseInt(s);

lambda表达式

stream

三类方法:获取Stream流--中间方法--终结方法

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList<String> list1=new ArrayList<>();
        list1.add("张lzy");
        list1.add("l");
        list1.add("张zy");
        list1.add("y");
        list1.add("hq");
        list1.stream().filter(name->name.startsWith("张")).filter(name->name.length()==3).forEach(System.out::println);
    }
}

获取stream流

新加:map   映射

        ArrayList<String> list = new ArrayList<>();
        list.add("张三丰-15");
        list.add("张无忌-90");
        list.stream().map(s -> s.split("-")[1]).forEach(System.out::println);

方法引用

::方法引用符

//对比
//Lambda简化写法
usePrintable(s -> System.out.println(s));

//方法引用
usePrintable(System.out::println);

异常

概况

概念

 编译时异常和运行时异常

Throwable中的常用方法:

  • public void printStackTrace():打印异常的详细信息。

 异常的作用

 try灵魂四问

//异常常用输出
e.printStackTrace();

自定义异常

目的:为了让控制台的报错信息更加的见名之意

文件

listFiles():获取该路径的所有内容

IO流

相对于程序  读入读出  内存是内往外是出

输出流:数据读入文件

输入流:数据从文件读出来

为什么要用IO:File类只能对文件本身进行操作,不能读写文件里面存储的数据。

IO流的分类

 

为什么使用字符流? 

答:当字节流遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件

缓冲流:能够高效读写

缓冲流加快速度的原理?

答:缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率

转换流:能够转换编码的    是字符流和字节流之间的桥梁

序列化流:能够持久化存储对象

 FileOutputStream

//把字符串转换为 byte[]类型
String str="lzyhaoshuai";
byte[] bWrite = str.getBytes();
//元素写出要是字符型  在后面+一个""
for (int i = 0; i < list.size(); i++) {
            if(i==list.size()-1){
                fw.write(list.get(i)+"");
            }else {
                fw.write(list.get(i)+"-");
            }
        }

两个好用工具包:Commons-io    hutool 概述 (hutool.cn)

多线程

线程相关

  • run()方法和start()方法的区别?

    run():封装线程执行的代码,直接调用,相当于普通方法的调用

    start():启动线程;然后由JVM调用此线程的run()方法

同一时间执行多个线程,提升性能。

并发:在同一时刻,有多个指令在单个CPU上交替执行。

并行:在同一时刻,有多个指令在多个CPU上同时执行。

进程:是正在运行的程序

线程:是进程中的单个顺序控制流,是一条执行路径

Java 提供了三种创建线程的方法:

  • 继承 Thread 类本身
  • 实现 Runnable 接口
  • 实现 Callable 接口。

Thread.currentThread().getName()  返回对当前正在执行的线程对象的引用

t2.setDaemon(true);   当普通线程执行完之后,那么守护线程也没有继续运行下去的必要了.

synchronized:锁

死锁:两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态

//同步方法
修饰符 synchronized 返回值类型 方法名(方法参数) { 
	方法体;
}

线程调度

  • 两种调度方式

    • 分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片

    • 抢占式调度模型:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些

  • Java使用的是抢占式调度模型

阻塞队列

 线程池

核心参数详解

public ThreadPoolExecutor(    int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
    
corePoolSize:   核心线程的最大值,不能小于0
maximumPoolSize:最大线程数,不能小于等于0,maximumPoolSize >= corePoolSize
keepAliveTime:  空闲线程最大存活时间,不能小于0
unit:           时间单位
workQueue:      任务队列,不能为null
threadFactory:  创建线程工厂,不能为null      
handler:        任务的拒绝策略,不能为null  
//创建线程池的两种方法

//创建一个默认的线程池
static ExecutorService newCachedThreadPool()   

//创建一个指定最多线程数量的线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                            核心线程数量,
                            最大线程数量,
                            空闲线程最大存活时间,
                            任务队列,
                            创建线程工厂,
                            任务的拒绝策略);

上下文切换

当前任务在执行完 CPU 时间片切换到另一个任务之前会先保存自己的状态,以便下次再切换回这个任务时,可以再加载这个任务的状态。任务从保存到再加载的过程就是一次上下文切换

资料文件夹中有面试常考。juc额外扩展资料

JUC是java.util.concurrent包的简称,在Java5.0添加,目的就是为了更好的支持高并发任务

网络编程

C/S:客户端  服务器

B/S:浏览器  服务器

反射

通过反射可以获取任意一个类的所有属性和方法

第一种forName最常用 

动态代理

无侵入式的给方法增强功能(类似后面的spingboot AOP)

 后续学习

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值