JavaSE新增

JavaSE:

一、DOS命令

  1. 盘符切换 D:

  2. 查看当前目录下的所有文件 / dir

  3. 切换目录 cd /d E:\typora //cd即change directory,跨盘符需加/d

  4. 返回上一级 cd ..

  5. 清空屏幕 cls //即clean screen

  6. 退出终端 exit

  7. 查看电脑ip ipconfig

  8. 打开应用 calc计算机 mspaint画图工具 notepad记事本

  9. ping命令,获取其IP信息,鼠标右键为粘贴

  10. 创建文件夹 md test //创建test文件夹

  11. 创建和删除文件 cd>a.txt del a.txt

  12. 删除目录 rd text //返回text上级目录即可删除text目录

二、注释

  1. ctrl+/ 单行

  2. ctrl+shift+/ 多行

  3. /** */ 文档注释 例如:@Description项目名、@Author作者

三、标识符

  1. 关键字

  1. 所有的标识符都应该以字母(A-Z或者a-z),美元符($)、或者下划线(_)开始

  • 首字符之后可以是字母(A-Z或者a-z),美元符($)、下划线()或数字的任何字符组合

  • 不能使用关键字作为变量名或方法名。

  • 标识符是大小写敏感的

  • 合法标识符举例:age、$salary、value、 _1_value

  • 非法标识符举例:123abc、-salary、#abo

public static void main(String[] args){ ​ String 王者荣耀 ="最强王者"; System.out.println(王者荣耀);

  • 可以使用中文命名,但是一般不建议这样去使用,也不建议使用拼音,很Low

 

四、数据类型及扩展面试题

(一)八大基础数据类型

public class Hello {
       public static void main(String[] args) {
//八大基本数据类型
//整数
           int num1 = 10;; //最常用

           byte num2 =20;
           short num3 =30;
           long num4 = 30L;//Long类型要在数字后面加个L
//小数:浮点数
           float num5 = 50.1F;//float类型要在数字后面加个F
           double num6 =3.141592653589793238462643;//字符
           char name ='国';
//字符串,string不是关键字,类
//String namea = "yf"
//布尔值:是非
           boolean flag = true;
//boolean flag = false;
           System.out.println(num1);
           System.out.println(num2);
           System.out.println(num3);
           System.out.println(num4);
           System.out.println(num5);
           System.out.println(num6);
           System.out.println(flag);
      }

}

(二)数据类型(扩展面试题)

1、整数

public class Hello {
   public static void main(String[] args){
//整数拓展: 进制 二进制0b 十进制 八进制0 十六进制0x
       int i = 10;
       int i2 = 010; //八进制0
       int i3 = 0x10;//十六进制0x 0~9 A~F 16
       System.out.println(i);

       System.out.println(i2);

       System.out.println(i3);
}}

image-20220426143404408

2、浮点数扩展

public class Hello {
   public static void main(String[] args){
       System.out.println("======= == = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ");
//========================================================================-
//浮点数拓展? 银行业务怎么表示?钱
//BigDecimal 数学工具类
//=========================================================================
//float   有限 离散   舍入误差 大约值
//double
       float f = 0.1f; //0.1
       double d = 1.0/10; //0.1
       System.out.println(f==d);
       System.out.println(f);
       System.out.println(d);//都是0.1却不相等,结果false
       
       float d1 = 156161651516615555f;
       float d2 = d1+1;
       System.out.println(d1==d2);//结果为true
       
       char c1= 'a';
       char c2= '中';
       System.out.println((int)c1);
       System.out.println((int)c2);//强制转换int型,结果为97,20013
       
       //Unicode编码:表示形式为U0000~UFFFF
       char c3= '\u0061';
       System.out.println(c3);//结果为a
             
}}

3、转义字符:

  • \t 空格

  • \n 换行

4、String类:

public class Hello {
   public static void main(String[] args) {
       String s1 = new String("Hello world");
       String s2 = new String("Hello world");
       System.out.println(s1==s2);//从内存分析,结果为false
  }
}

5、布尔值类型:

boolean flag = true;
if(flag==true){}//新手
if(flag){}//老手

6、String与int之间的转换:

链接:Java String字符串和整型int的相互转换 (biancheng.net)

(三)类型转换

由低到高:char << byte << short << int << long << float <<double

注意点: 1.不能对布尔值进行转换 2.不能把对象类型转换为不相干的类型 3.在把高容量转换到低容量的时候,强制转换 4.转换的时候可能存在内存溢出,或者精度问题

(四)变量的命名规范

1.所有变量、方法、类名:见名知意 2.类成员变量:首字母小写和驼峰原则:monthSalary除了第一个单词以外,后面的单词首字母大写 lastname lastName 3.局部变量:首字母小写和驼峰原则 4.常量:大写字母和下划线:MAX VALUE 5.类名:首字母大写和驼峰原则:Man,GoodMan 6.方法名:首字母小写和驼峰原则:run(),runRun()

五、运算符

Java 语言支持如下运算符:优先级()

  • 算术运算符:+,-,*,/,%,++,--

  • 赋值运算符:=

  • 关系运算符:>,<,>=,<=,==,!=instanceof

  • 逻辑运算符: &&,||,!

  • 位运算符: &,|,^,~,>>,<<,>>>(了解!!!)

  • 条件运算符:? :

  • 扩展赋值运算符:+=,-=,*=,/=

(一)自增自减,幂运算

public class Day1 {
   public static void main(String[] args) {
          int a = 3 ;
          int b = a++ ;//先执行b=a,再执行a=a+1
       System.out.println(a);//a=4
          int c = ++a ;//先执行a=a+1,再执行c=a
       System.out.println(a);//a=5
       System.out.println(b);//b=3
       System.out.println(c);//c=5
       
       //幂运算 借助Math类来操作
       double x = Math.pow(2,3);
       System.out.println(x);//x=8
  }
}

(二)逻辑运算符

public class Day2 {
   public static void main(String[] args) {
       //与(&&)、或(||)、非(!)运算
       boolean a = true ;
       boolean b = false;
       System.out.println("a&&b的结果是:"+(a&&b));//false
       System.out.println("a||b的结果是:"+(a||b));//true
       System.out.println("!(a&&b)的结果是:"+!(a&&b));//true

       //短路运算
       int c = 3 ;
       boolean d = (c<2)&&(c++>5);//短路运算,c++>5不执行
       System.out.println(d);
       System.out.println(c);//c=3
  }
}

(三)位运算符(面试题)

public class Day3 {
   public static void main(String[] args) {
       /*
       A=0011 1100
       B=0000 1101
       ----------------------
       A&B = 0000 1100   //与运算:有一个为0就是0
       A|B = 0011 1101   //或运算:有一个为1就是1
       A^B = 1100 1110   //异或运算,相同为1
       ~B = 1111 0010   //非运算,取反

       2*8 = 16       2*2*2*2 //效率极高
       <<   *2
       >>   /2

       0000 0000     0
       0000 0001     1
       0000 0010     2
       0000 0100     4
       0000 1000     8
       0001 0000     16
       */
  }
}

(四)字符拼接(面试题)

public class Day4 {
   public static void main(String[] args) {
       int a = 2;
       int b = 3;
       a += b ;//a = a+b
       a -= b ;//a = a-b
       System.out.println(a);

       //字符串连接
       System.out.println(a+b);//结果为5
       System.out.println(""+a+b);//字符拼接,结果为23
       System.out.println(a+b+"");//a+b先运算,结果为5
  }
}

(五)三元运算符

public class Day5 {
   public static void main(String[] args) {
       //x ? y : z
       //if x==true {x=y ; else x=z ;}
       int score = 90 ;
       String type = score < 60 ? "不及格" : "及格" ;
       System.out.println(type);//及格
  }
}

六、包机制

1.为了更好地组织类,Java提供了包机制,用于区别类名的命名空间。包语句的语法格式为:

package pkg1[. pkg2[. pkg3…]];

例如:com.zhang.www com.wang.www

2.一般利用公司域名倒置作为包名;

3.为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。

使用"import"语句可完成此功能:

import package1[.package2..].(classname|*);

七、JavaDoc

javadoc命令是用来生成自己API文档的

参数信息

  • @author 作者名

  • @version 版本号

  • @since 指明需要最早使用的jdk版本

  • @param 参数名

  • @return 返回值情况

  • @throws 异常抛出情况

package com.Yaof.www;

/**
* @author Yaof
* @version 1.0
* @since 1.8
*/

public class Day6 {
   String name;

   /**
    * @auther Yaof
    * @param name
    * @return
    * @throws Exception
    */
   public  String test(String name) throws  Exception{ //抛出异常
       return name;
  }

}

生成Javadoc文档:

D:\JavaSE\src\com\Yaof\base>javadoc -encoding UTF-8 -charset UTF-8 Day6.java

作业:用idea生成Javadoc文档:

先在Day6目录下新建一个用于存放Javadoc文档的文件夹Doc,再去IDEA工具中找到生成Doc文档,最后更改输出目录,区域设置为zh_CN,其他命令实参为-encoding UTF-8 -charset UTF-8,确定后Doc生成在文件夹中。

八、用户交互Scanner

next(): 1、一定要读取到有效字符后才可以结束输入。 2、对输入有效字符之前遇到的空白,next()方法会自动将其去掉。 3、只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。 4、next() 不能得到带有空格的字符串。

nextLine(): 1、以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符。 2、可以获得空白。

(一) next ( )

package com.Yaof.base.Scanner;

import java.util.Scanner;

public class Demo01 {
public static void main(String[] args) {
//创建一个扫描器对象,用于接收键盘数据
Scanner scanner = new Scanner(System.in);
System.out.println("使用next方式接收:");

//判断用户有没有输入字符串
if (scanner.hasNext()){
//使用next方式接收
String s = scanner.next();
System.out.println("输入的内容为:"+s);//输入:hello wy 结果:hello
}

scanner.close();//凡是IO流的类,不关闭就会一直占用资源
}
}

(二) nextline ( )

package com.Yaof.base.Scanner;

import java.util.Scanner;

public class Demo02 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("使用nextLine接收:");

//判断用户有没有输入字符串
if (scanner.hasNext()){
String str = scanner.nextLine();
System.out.println("输入的内容为:"+str);//输入:Hello WY 输出:Hello WY
}
scanner.close();
}
}
package com.Yaof.base.Scanner;

import java.util.Scanner;

public class Demo03 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入:");

String str = scanner.nextLine();
System.out.println("输入的内容为:"+str);//输入:Hello WY 输出:Hello WY
scanner.close();
}
}

(三)输入输出整数与小数

package com.Yaof.base.Scanner;

import java.util.Scanner;

public class Demo04 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//从键盘输入数据
int i = 0 ;
float f = 0.0f;
System.out.print("请输入整数:");
//输入、输出整数
if(scanner.hasNextInt()){
i=scanner.nextInt();
System.out.println("输出的整数为:"+i);
}else{
System.out.println("输入的不是整数!");
}

//输入、输出小数
System.out.println("请输入小数:");
if(scanner.hasNextFloat()){
f=scanner.nextFloat();
System.out.println("输出的小数为:"+f);
}else{
System.out.println("输入的不是小数!");
}


scanner.close();
}
}

(四)练习

可以输入多个数字,求出总和、平均数,通过换行输入下一个,输入非数字结束并输出执行结果

package com.Yaof.base.Scanner;

import java.util.Scanner;

public class Deme05 {
public static void main(String[] args) {
//可以输入多个数字,求出总和、平均数,通过换行输入下一个,输入非数字结束并输出执行结果
Scanner scanner = new Scanner(System.in);

double sum = 0 ;
int num = 0 ;
System.out.println("请输入数字:");
while (scanner.hasNextDouble()){
double x = scanner.nextInt();
sum = sum + x ;
num++;
System.out.print("sum="+sum);
System.out.println(" num="+num);
}
System.out.println("总和是"+sum);
System.out.println("平均数是"+sum/num);
scanner.close();
}
}

九、结构

(一)顺序结构

语句与语句按照顺序进行,是java的基本结构,是任何一个算法都离不开的一种基本算法结构。

(二)选择结构

1.if

if 包括 if、if else 、if else if 、if if

比较简单,不细说了,下面是判断是否及格的例子

package com.Yaof.base.struct;

import java.util.Scanner;

public class IfDemo01 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入成绩:");
int grade = 0;
grade = scanner.nextInt();
if(grade<60){
System.out.println("成绩不及格!");
}
else{
System.out.println("恭喜你,及格了!");
}

scanner.close();
}
}

2.switch

多选择,每一个选择称为分支

case 具有穿透性,swtich 匹配一个具体的值

package com.Yaof.base.struct;

import java.util.Scanner;

public class SwitchDemo02 {
   public static void main(String[] args) {
       Scanner scanner = new Scanner(System.in);
       System.out.print("请输入姓名:");
       String s = scanner.nextLine();
       switch (s){
           case "蔡徐坤" :
               System.out.println("篮球之星");
               break;
           case "罗志祥":
               System.out.println("时间大师");
               break;
           case "吴亦凡":
               System.out.println("大碗宽面");
               break;
           default:
               System.out.println("输入大明星好吗");
      }
       scanner.close();
  }
}

(三)循环结构

1.while

输入一个整数n,计算出1+2+3+...+n的值:

package com.Yaof.base.struct;

import sun.security.rsa.RSASignature;

import java.util.Scanner;

public class WhileDemo03 {
   public static void main(String[] args) {
       //输出1~输入的某数字之和
       Scanner scanner = new Scanner(System.in);
       System.out.print("请输入一个整数:");
       int sum = 0 ;
       int n = scanner.nextInt();
       int m = 1 ;
       while (m<=n){

           sum=sum+m;
           m++;
      }
       System.out.println("从1到"+n+"相加的值为:"+sum);//输入100,输出5050
  }
}

2.do while

先执行,后判断

do{ 语句

}while(条件);

3.for

(1)输入一个n,计算1~n奇数之和:

package com.Yaof.base.struct;

import java.util.Scanner;

public class ForDemo04 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入:");
int i = scanner.nextInt();

int sum = 0 ;
for( int k=1 ; k<=i ; k+=2){ //此处为奇数之和,k=0时为偶数之和
sum = k + sum ;
}
System.out.println(sum);
scanner.close();
}
}

(2)高阶调用法:

输入一个整数,判断奇偶,并计算出它的奇偶之和

package com.Yaof.base.struct;

import java.util.Scanner;

public class ForDemo04 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入一个整数:");
int i = scanner.nextInt();
int oldsum = 0;//奇数
int evensum= 0;//偶数

if (i % 2 == 1) {//判断是奇数
System.out.print(i+"为奇数,奇数和为:");
p(i, oldsum, evensum);
}else {//偶数
System.out.print(i+"为偶数,奇数和为:");
p(i, oldsum, evensum);
}
scanner.close();
}

private static void p(int i, int oldsum, int evensum) {
for (int q = 1; q <= i; q += 2) { //此处为奇数之和
evensum = q + evensum;
}
System.out.print(evensum);
System.out.print(" "+"偶数和为:");
for (int k = 0; k <= i; k += 2) { //此处为偶数之和
oldsum = k + oldsum;
}
System.out.println(oldsum);
}
}

(3)99乘法口诀:

package com.Yaof.base.struct;

public class ForDemo05 {
public static void main(String[] args) {
for(int i = 1 ;i<=9;i++){
System.out.println();
for(int j = 1 ;j<=i;j++){//首先找出这一规律,横排
System.out.print(" "+j+"×"+i+"="+i*j);
}
}
}
}

(4)打印三角形

package com.Yaof.base.struct;

public class ThreeWayDemo07 {
public static void main(String[] args) {
//打印三角形,5行
for(int i=1;i<=5;i++){

for(int j=5;j>=i;j--){
System.out.print(" ");
}
for(int k=1;k<=i;k++){
System.out.print("*");//三角形左边部分
}
for(int a=1;a<i;a++){//三角形右边部分,这里是a<i,没有=
System.out.print("*");
}
System.out.println();//控制换行
}
}
}

(5)增强for循环

package com.Yaof.base.struct;

public class ForMaxDemo06 {
public static void main(String[] args) {
int[] arr= {1,2,3,4,5};
for (int n :arr){ //增强For循环
System.out.println(n);//将数组arr中的逐个打印
}
}
}

(6)break和continue

break使用后直接跳出循环

continue使用后跳过某一条循环,接着执行下一条循环

十、方法

public static void main(String[ ] args)

//其中public static 是修饰符,void是空的返回值,main就是方法名

(一)简单方法调用

1.调用选择结构中的例子,理解实参、形参

package com.Yaof.base.Method;

import java.util.Scanner;

public class Demo01 {
public static void main(String[] args) {//调用add和test方法
add(1,2);//实参,实际参数
test();
}
public static void test(){//这是选择结构中的例子
Scanner scanner = new Scanner(System.in);
System.out.print("请输入成绩:");
int grade = 0;
grade = scanner.nextInt();
if(grade<60){
System.out.println("成绩不及格!");
}
else{
System.out.println("恭喜你,及格了!");
}

scanner.close();
}
public static int add(int aaa, int bbb){//形参,形式参数,用于被调用
return (aaa+bbb);
}
}

2.调用比大小的方法,return可以终止方法

package com.Yaof.base.Method;

public class Demo02 {
public static void main(String[] args) {
max(1,2);
}
public static int max(int a,int b){
int x = a>b?a:b;//比较大小
System.out.println(x);
return 0;//终止方法
}
}

(二)方法的重载

重载就是在一个类中,有相同的函数名称,但形参不同的函数。

方法的重载的规则:

  • 方法名称必须相同。

  • 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。

  • 方法的返回类型可以相同也可以不相同。

  • 仅仅返回类型不同不足以成为方法的重载。

实现理论: 方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。

package com.Yaof.base.Method;

public class Demo03 {
public static void main(String[] args) {
max(1, 2);//调用int
max(1.1,2.5);//调用double
}

public static int max(int a, int b) {
int x = a > b ? a : b;
System.out.println(x);
return 0;//终止方法
}
public static double max(double a, double b) {//max方法重载
double x = a > b ? a : b;
System.out.println(x);
return 0;//终止方法
}
}

(三)命令行传递参数

有时候希望运行时传递参数,需要用mian()函数实现:

首先在idea中写出如下代码,然后在终端cd到当前目录,这里是Method,执行javac Demo04.java编译

再cd.. 返回到src目录下,执行java com.Yaof.base.Method.Demo04 I Love You即可输出

package com.Yaof.base.Method;

public class Demo04 {
public static void main(String[] args) {
for(int i=0;i<args.length;i++){
System.out.println("args["+i+"]:"+args[i]);
}
}
}

(四)可变参数

下面是一个可变长参数判断大小的例子:

package com.Yaof.base.Method;

public class Demo05 {
public static void main(String[] args) {
Demo05 demo05= new Demo05();//这里调用一下Demo05的类
Demo05.Max(12,13,11,10,52,1,3);
Demo05.Max(new double[]{1.1,1.3,1.2});
}
public static void Max(double... num){//可变长的double类型参数num
if(num.length==0){
System.out.println("No argument passde");//无参数传递
return;
}
double result = num[0];

for (int i=1;i<num.length;i++){
if(num[i]>result){//判断大小
result = num[i];
}
}
System.out.println("The max value is"+result);//结果是The max value is 52.0
//The max value is 1.3
}
}

(五) 递归

A方法调用B方法,我们很容易理解! 递归就是:A方法调用A方法!就是自己调用自己

利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。

递归结构包括两个部分: 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。

递归体:什么时候需要调用自身方法。

下面是计算阶乘的递归例子:

package com.Yaof.base.Method;

import java.util.Scanner;

public class Demo07 {
   public static void main(String[] args) {//计算阶乘
       Scanner scanner = new Scanner(System.in);
       int a = scanner.nextInt();//获取键盘输入数字
       System.out.println(multiply(a));//调用乘法multiply方法并输出
       scanner.close();
  }
   public static int multiply(int a){
       if (a == 1){
           return 1;
      }else {
           return a*multiply(a-1);//递归实现
      }
  }
}

(六) 简单计算器

(计算器Calculator)

package com.Yaof.base.Method;

import java.util.Scanner;

public class CalculatorDemo06 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
System.out.println("计算器:");
int a = scanner.nextInt();
String b = scanner.next();
int c = scanner.nextInt();
switch (b){
case "+":
add(a,c);//加法
break;
case "-":
subtract(a,c);//减法
break;
case "*":
multiply(a,c);//乘法
break;
case "/":
except(a,c);//除法
break;
default:
System.out.println("输入错误!");
}

scanner.close();
}
public static double add(int a,int b){//加法
System.out.println(a+"+"+b+"="+(a+b));
return a+b;
}
public static double subtract(int a,int b){//减法
System.out.println(a+"-"+b+"="+(a-b));
return a-b;
}
public static double multiply(int a,int b) {//乘法
System.out.println(a + "*" + b + "=" + (a * b));
return a * b;
}
public static double except(int a,int b) {//除法
System.out.println(a + "/" + b + "=" + (a / b));
return a /b;
}
}

十一、数组

1、数组的定义

首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法: dataType[ ] arrayRefVar; // 首选的方法 dataType arrayRefVar[ ]; // 效果相同,但不是首选方法,早期的c、c++

Java语言使用new操作符来创建数组,语法如下:

dataType[ ] arrayRefVar = new dataType [arraysize];

例如:int [ ] arr = new arr[10] ;

数组的元素是通过索引访问的,数组索引从0开始。获取数组长度: arrays.length

下面是数组的简单例子:

package com.Yaof.base.Array;

public class Demo01 {
public static void main(String[] args) {
int [] arr = new int[5];
arr[0]=1;
arr[1]=2;
arr[2]=3;
arr[3]=4;
arr[4]=5;
int sum=0;
for(int i=0;i<arr.length;i++){
sum=arr[i]+sum;//计算数组中值的和
}
System.out.println(sum);
}
}

2、数组的初始化

静态初始化和动态初始化

package com.Yaof.base.Array;

public class ArrayDemo02 {
public static void main(String[] args) {
int [] a={1,3,5,7,9};//静态初始化,直接给数组赋值,数组无法改变
int [] b= new int[5];//动态初始化,int默认是0,String默认是NULL,数组数值可变化
System.out.println(a[0]);
System.out.println(b[0]);
System.out.println(b[1]);
}
}

3、数组的四个基本特点

  • 其长度是确定的。数组一旦被创建,它的大小就是不可以改变的。

  • 其元素必须是相同类型,不允许出现混合类型。

  • 数组中的元素可以是任何数据类型,包括基本类型和引用类型。

  • 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。

  • 数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的

4、注意点和小结

下标的合法区间:[0,length-1],如果越界就会报错: public static void main(String[ ] args) { int[ ] a=new int[2]; System.out.println(a[2]); } 报错内容:ArrayIndexOutOfBoundsException:数组下标越界异常!

小结: 数组是相同数据类型(数据类型可以为任意类型)的有序集合。

数组也是对象,数组元素相当于对象的成员变量。

数组长度的确定的,不可变的。如果越界,则报:ArrayIndexOutofBounds

5、数组的使用

  • 普通的For循环(最常用)

  • For-Each 循环(用于打印数组)

  • 数组作方法入参(常用)

  • 数组作返回值(下方进阶使用中的反转数组)

简单使用:

package com.Yaof.base.Array;

public class ArrayDemo03 {
public static void main(String[] args) {
int [] arr = {1,3,5,4,2};
//打印数组元素
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
System.out.println("===============");

//数组元素求和
int sum = arr[0];
for (int i = 1; i < arr.length; i++) {
sum += arr[i];
}
System.out.println(sum);
System.out.println("===============");

//求最大元素
int max=arr[0];
for (int i = 0; i < arr.length; i++) {
if(max<arr[i]){
max=arr[i];
}
}
System.out.println(max);
}
}

进阶用法:

package com.Yaof.base.Array;

public class ArrayDemo04 {
public static void main(String[] args) {
int [] arr = {1,2,3,4,5};
/* //增强for循环,适合打印输出
for (int i : arr) {
System.out.println(i);
}*/
int[] reverse = reverse(arr);//防止混乱,输出arr是初始值的情况
printarray(reverse);
}

//打印arr中的元素
public static void printarray(int [] arr){
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}

//反转元素
public static int[] reverse(int [] arr){
int [] arr2 = new int[arr.length];//防止调换和return返回时混乱
for (int i = 0,j=arr2.length-1; i < arr.length; i++,j--) {
arr2[j]=arr[i];//调换位置

}
return arr2;
}
}

6、二维数组和多维数组

package com.Yaof.base.Array;

public class ArrayDemo05 {
   public static void main(String[] args) {
       int [] [] arr = {{1,2},{1,2,3},{1,2,3,4}};
//       ArrayDemo04.printarray(arr[1]);//调用前面打印一维数组的方法
       printarrays(arr);

  }
   public static void printarrays(int[][] arrs){
       for (int i = 0; i < arrs.length; i++) {//遍历int[]
           for (int j = 0; j < arrs[i].length; j++) {//遍历int [][]
               System.out.print(" "+arrs[i][j]);//打印
          }
           System.out.println();//换行
      }
  }
}

7、Arrays数组的工具类

java.util.Arrays 由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。查看JDK帮助文档 Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而"不用"使用对象来调用(注意:是"不用"而不是"不能")

具有以下常用功能: 给数组赋值:通过fill方法。 对数组排序:通过sort方法,按升序。 比较数组:通过 eguals 方法比较数组中元素值是否相等。 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。

package com.Yaof.base.Array;

import java.util.Arrays;

public class ArrayDemo06 {
public static void main(String[] args) {
int[] arr = {2,3,5,9,12,1,20,4};
int[] arr2={1,2,3};
//调用Array类
Arrays.fill(arr,1,3,0);//将数组的1-3位置填充0
Arrays.sort(arr);//调用升序排序
System.out.println(Arrays.toString(arr));//打印数组中的元素
System.out.println("==============");
System.out.println(Arrays.equals(arr,arr2));//判断数组是否相等
System.out.println("==============");
System.out.println(Arrays.binarySearch(arr,0));//二分法查找,结果为1,没搞懂
}
}

8、冒泡排序

  • 两层循环结构:外部控制轮次,内层依次比较

  • 时间复杂度为O(n2)

package com.Yaof.base.Array;

import java.util.Arrays;
import java.util.Scanner;
import java.util.stream.StreamSupport;

public class ArrayDemo07 {
//冒泡排序
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("=======================");
System.out.println("用倒序排序 输入的数字");
System.out.println("=======================");
System.out.print("请输入一个整数:");
int n = scanner.nextInt();//从键盘接收数字
int[] m= new int[n];//定义数组m,大小为n
for(int i=0;i<m.length;i++){//将数组m赋值1,2,3...n
m[i]=i+1;
}
sort(m);//调用下方排序方法
System.out.println(Arrays.toString(m));//输出数组
scanner.close();
}
public static int[] sort(int[] x){
boolean flag = false;//为节省时间,加快运行
for (int i = 0; i < x.length; i++) {//外部循环,控制排序轮次
for (int j = 1; j < x.length-i; j++) {//内部循环,依次比较,将大数放在前面
if(x[j-1]<x[j]){
int temp = x[j-1];
x[j-1]=x[j];
x[j]=temp;
flag=true;
}
if(flag==false){//节约时间
break;
}
}
}
return x;
}
}

9、稀疏数组

package com.Yaof.base.Array;

import java.util.Arrays;

public class ArrayDemo08 {
public static void main(String[] args) {
int[][] arr = new int[11][11];
arr[1][2]=1;
arr[2][3]=2;
System.out.println("原始的数组:");
//打印数组
for (int[] ints : arr) {//arr.for自动
for (int anInt : ints) {//ints.for自动
System.out.print(anInt+"\t");//加上空格更美观
}
System.out.println();
}
/* for (int i = 0; i < arr.length; i++) {
System.out.println(Arrays.toString(arr[i]));
}*/
//记录数组中有效值个数
int sum=0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if(arr[i][j]!=0){
sum++;
}
}
}
System.out.println("有效值个数:"+sum);
System.out.println("========================");
//创建稀疏数组
int[][] arr2 = new int[sum+1][3];
arr2[0][0]=arr.length;
arr2[0][1]=arr[0].length;
arr2[0][2]=sum;
System.out.println();
//遍历二维数组,将数值存放到稀疏数组
int count = 0;//起到计数作用
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if(arr[i][j]!=0){
count++;
arr2[count][0]=i;//存放第一列数据
arr2[count][1]=j;//存放第二列数据
arr2[count][2]=arr[i][j];//存放第三列数据
}
}
}
//输出稀疏数组
System.out.println("稀疏数组:");
for (int i = 0; i <arr2.length ; i++) {//打印数组
System.out.println(arr2[i][0]+"\t"+
arr2[i][1]+"\t"+
arr2[i][2]+"\t");
}
//用稀疏数组还原数组
int[][] arr3=new int[arr2[0][0]][arr2[0][1]];//还原数组大小
for (int i = 1; i < arr2.length; i++) {
arr3[arr2[i][0]][arr2[i][1]]=arr2[i][2];//还原数组元素及存放位置
}
System.out.println("=================");
System.out.println("还原结果:");
//打印还原后的数组
for (int[] ints : arr3) {//arr3.for自动
for (int anInt : ints) {//ints.for自动
System.out.print(anInt+"\t");//加上空格更美观
}
System.out.println();
}
/*for (int i = 0; i < arr3.length; i++) {
for (int j = 0; j < arr3[0].length; j++) {
System.out.print(arr3[i][j]+"\t");
}
System.out.println();
}*/
}
}

十二、面向对象

(一)面向对象

面向对象编程(Object-Oriented Programming,OOP) 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据

抽象

三大特性:

  • 封装

  • 继承

  • 多态

总结:

  • 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。

  • 从代码运行角度考虑是先有类后有对象。类是对象的模板。

1、新建学生类和两个对象

package com.Yaof.oop.demo01;

public class Student {
String name;
int age;
}
package com.Yaof.oop.demo01;

public class Demo03 {
public static void main(String[] args) {
Student yf = new Student();
Student wy = new Student();
yf.age=3;
yf.name="Yaof";
wy.name="Wangy";
wy.age=2;
System.out.println(yf.name);
System.out.println(yf.age);
System.out.println("==========");
System.out.println(wy.name);
System.out.println(wy.age);
}
}

2、构造器

  • 和类名相同

  • 没有返回值

作用:

  • new 本质是在调用构造方法

  • 初始化对象的值

注意点:

  • 定义有参构造之后,如果想使用无参构造,显示的定义一个无参构造

Alt+Insert 快捷构造参数

this. = 代表当前类的,后面等于的值是参数传进来的值

package com.Yaof.oop.demo02;

public class Person {
   String name;
   int age;

   public Person() {//无参构造
  }
   
   public Person(String name, int age) {//有参构造
       this.name = name;
       this.age = age;
  }
}
package com.Yaof.oop.demo02;

import javax.naming.Name;

public class demo01 {
   public static void main(String[] args) {
       Person Yf = new Person();//调用无参构造
       Yf.age=3;
       Yf.name="Yaof";
       Person person = new Person("wy",3);//调用有参构造
       System.out.println(Yf.name);
       System.out.println(Yf.age);
       System.out.println("************");
       System.out.println(person.name);
       System.out.println(person.age);
  }
}

3、总结:

1.类与对象 类是一个模板:抽象,对象是一个具体的实例 2.方法: 定义、调用! 3.对应的引用 引用类型: 基本类型(8) 对象是通过引用来操作的:栈-->堆 4.属性:字段Field 成员变量 默认初始化: 数字: 0 0.0 char : u0000 boolean: false 引用:null 修饰符 属性类型属性名=属性值! 5.对象的创建和使用 必须使用new 关键字创造对象,构造器 Person kuangshen= newPerson((),

例如: 对象的属性 kuangshen.name 对象的方法 kuangshen.sleep()

  1. 类: 静态的属性——属性 动态的行为——方法

(二)封装

package com.Yaof.oop.demo03;

public class Student {//封装属性
private String name;
private int id;
private int age;
private char sex;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public int getAge() {
return age;
}

public void setAge(int age) {
if(age<100 &age>0){//设置年龄范围是1~99
this.age = age;
}else{
System.out.print("年龄出错!!");
}
}

public char getSex() {
return sex;
}

public void setSex(char sex) {
this.sex = sex;
}
}
package com.Yaof.oop.demo03;

import sun.plugin2.message.GetNameSpaceMessage;

public class Demo01 {
public static void main(String[] args) {
Student yf = new Student();//构造新的学生对象
System.out.println(yf.getId());//id未设置值,默认为0
yf.setName("Yaof");//设置姓名
yf.setAge(1);
System.out.println(yf.getAge());//输出1

}
}

(三)继承

1.实例

(1)新建一个父类

package com.Yaof.oop.demo03;

public class Father /*extends Object*/{
private int money= 10_0000_0000;//私有
public String car = "奔驰";
public String house;
public void girl(){
System.out.println("迪丽热巴");
}

public int getMoney() {
return money;
}

public void setMoney(int money) {
this.money = money;
}
}

(2)新建一个子类

package com.Yaof.oop.demo03;

public class Son extends Father{

}

(3)开始继承

package com.Yaof.oop.demo03;

public class Demo02 {
public static void main(String[] args) {
Son son =new Son();//儿子继承了父亲
son.girl();//父亲的girl
son.setMoney(5_0000_0000);//父亲的钱用set设置
System.out.println(son.getMoney());//输出钱5亿
System.out.println(son.car);//输出奔驰
}
}

2、supper关键字

super注意点: 1.super调用父类的构造方法,必须在构造方法的第一个 2.super 必须只能出现在子类的方法或者构造方法中! 3.super和this不能同时调用构造方法!

与 this比较: 代表的对象不同: this:本身调用者这个对象 super: 代表父类对象的应用

前提 this:没有继承也可以使用 super:只能在继承条件才可以使用构造方法 this();本类的构造 super():父类的构造!

(1)父类

package com.Yaof.oop.demo03;

public class Father1 {
protected String name = "父亲";

public Father1() {
System.out.println("父亲的无参构造");
}

public void method(){
System.out.println("父系的方法");
}
}

(2)子类

package com.Yaof.oop.demo03;

public class Son1 extends Father1{
String name = "儿子";

public Son1() {
System.out.println("儿子的无参构造");
}

public void method(){
super.method();
System.out.println(super.name);
System.out.println("儿子的方法");
System.out.println(this.name);
}
}

(3)启动类

package com.Yaof.oop.demo03;

import java.lang.reflect.Method;

public class Appication {
public static void main(String[] args) {
String name = "启动类";
Son1 son1 = new Son1();
son1.method();
System.out.println(name);
}
public void method(){
System.out.println("启动类的方法");
/*结果:
父亲的无参构造
儿子的无参构造
父系的方法
父亲
儿子的方法
儿子
启动类
*/
}
}

3、重写

重写都是方法的重写,和属性无关!需要有继承关系,子类重写父类的方法! 子类的方法名和父类要一致,方法体不同!

  1. 方法名必须相同

  2. 参数列表列表必须相同

  3. 修饰符:范围可以扩大但不能缩小: public>Protected>Default(默认)>private

  4. 抛出的异常:范围,可以被缩小,但不能扩大 ClassNotFoundException --> Exception(大)

为什么需要重写: 父类的功能,子类不一定需要,或者不一定满足!

Alt+ Insert >> Override(重写)

package com.Yaof.oop.demo03;

public class Father3 {
public void test(){
System.out.println("父类的方法");
}
public static void test1(){
System.out.println("静态的父类");
}
}
package com.Yaof.oop.demo03;

public class Son3 extends Father3{
public void test(){
System.out.println("子类的方法");
}
public static void test1(){
System.out.println("静态的子类");
}
}
package com.Yaof.oop.demo03;

public class Appication3 {
public static void main(String[] args) {
Son3 a= new Son3();
a.test1();//静态的子类
a.test();//子类的方法
Father3 b = new Son3();
b.test1();//静态的父类
b.test();//子类的方法 重写
}
}

(四)多态

1、多态实例

即同一方法可以根据发送对象的不同而采用多种不同的行为方式。 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)

多态存在的条件: 有继承关系 子类重写父类方法 父类引用指向子类对象

注意:多态是方法的多态,属性没有多态性。 instanceof (类型转换) 引用类型

多态注意事项: 1.多态是方法的多态,属性没有多态 I 2.父类和子类,有联系类型转换异常! ClassCastException! 3.存在条件: 继承关系,方法需要重写,父类引用指向子类对象! Father f1 =new

不能重写:

  • static 方法,属于类,它不属于实例

  • final 常量;

  • private方法;

package com.Yaof.oop.demo04;

public class Father {
   public void test(){
       System.out.println("父类的方法");
  }
}
package com.Yaof.oop.demo04;

public class Son extends Father{
   public void test(){
       System.out.println("子类的方法");
  }
   public void eat(){
       System.out.println("子类独有的吃");
  }
}
package com.Yaof.oop;

import com.Yaof.oop.demo04.Father;
import com.Yaof.oop.demo04.Son;

public class Application {
   public static void main(String[] args) {
       Son a = new Son();
       Father b = new Son();
       Object c = new Son();
       a.test();//子类的方法
       b.test();//子类的方法
      ((Son) b).eat();//强制转换为Son
  }
}

2、 instanceof 和类型转换

Father father = new Son();

father instanceof X 得到的是boolean类型,如果father、X之间无继承关系则报错,如果有,则编译通过,但如果X与Son无继承就为false,有则是true

//instanceof
package com.Yaof.oop;
import com.Yaof.oop.demo04.Daughter;
import com.Yaof.oop.demo04.Father;
import com.Yaof.oop.demo04.Son;
import org.omg.CORBA.Object;

public class Application {
public static void main(String[] args) {
/* Object object = (Object) new Son();//报错,有联系类型转换异常! ClassCastException!
System.out.println(object instanceof Son);
System.out.println(object instanceof Father);
System.out.println(object instanceof Object);
System.out.println(object instanceof Daughter);*/
System.out.println("==================");
Father father = new Son();
System.out.println(father instanceof Son);
System.out.println(father instanceof Father);
System.out.println(father instanceof Object);
System.out.println(father instanceof Daughter);
// System.out.println(father instanceof String);//报错
System.out.println("==================");
Son son = new Son();
System.out.println(son instanceof Son);
System.out.println(son instanceof Father);
System.out.println(son instanceof Object);
/* System.out.println(son instanceof Daughter);
System.out.println(son instanceof String);*///报错
Object object = new Father();
}
}
package com.Yaof.oop;

import com.Yaof.oop.demo04.Daughter;
import com.Yaof.oop.demo04.Father;
import com.Yaof.oop.demo04.Son;
//类型转换
public class Application {
/* Object>Father>Son
* 高 >>>>>>>>> 低
*/
public static void main(String[] args) {
Father father = new Son();
((Son) father).eat();//高到低,需要强制转换
Son son = new Son();
Father a = son;//低到高,随意转换
}
}

3、小结

  1. 父类引用指向子类的对象

  2. 把子类转换为父类,向上转型

  3. 把父类转换为子类,向下转型: 强制转换

  4. 方便方法的调用,减少重复的代码 简洁

封装、继承、多态 抽象类,接口 更抽象

(五)static静态

package com.Yaof.oop.demo05;

public class Demo01 {
private static String name;//静态
private int age;//非静态

public static void main(String[] args) {
Demo01 demo01= new Demo01();
Demo01.name="dd";//静态
demo01.age = 5;//非静态
System.out.println(name);
System.out.println(demo01.age);
}
}
package com.Yaof.oop.demo05;

public class Demo02 {
{
System.out.println("匿名代码块");//可以执行多次,可用于赋初始值等
}
static {
System.out.println("静态代码块");//只在程序启动时执行一次
}

public static void main(String[] args) {
Demo02 demo02 = new Demo02();
System.out.println("构造一下");
System.out.println("===========");
Demo02 a = new Demo02();
System.out.println("再构造一个");
/*结果:
静态代码块
匿名代码块
构造一下
===========
匿名代码块
再构造一个*/
}
}

导入静态包

package com.Yaof.oop.demo05;

import java.sql.SQLOutput;
import static java.lang.Math.random;//静态导入包,导入Math的random方法

public class Demo03 {
public static void main(String[] args) {
System.out.println(random());//可以直接使用random方法
}
}

Final:被final修饰后的类无法成为父类,就是断子绝孙,如public final class son{ }

(六)抽象类

通过子类来写方法

abstract 抽象类:类 extends: 单继承~ (接口可以多继承)

package com.Yaof.oop.demo05;
   public abstract class Action {
//约束~有人帮我们实现~
//abstract ,抽象方法,只有方法名字,没有方法的实现! public abstract void doSomething();
//1.不能new这个抽象类,只能靠子类去实现它;约束!
// 2.抽象类中可以写普通的方法~
// 3.抽象方法必须在抽象类中~
// 抽象的抽象:约束~
//思考题? new, 存在构造器么?     答案:无法实例化,不存在构造器
//存在的意义 抽象出来~提高开发效率
  }

(七)接口

作用:

  1. 约束

  2. 定义一些方法,让不同的人实现~10---> 1

  3. public abstract

  4. public static final

  5. 接口不能被实例化~,接口中没有构造方法~

  6. implements可以实现多个接口

  7. 必须要重写接口中的方法~

UserService接口

package com.Yaof.oop.demo06;

public interface Userservice {//interface定义接口的关键字
   int age = 10 ;
   //接口中的所有定义其实都是抽象的public abstract
   void add(String name);
   void delete(String name);
   void update(String name);
   void query(String name);

}

TimeService接口

package com.Yaof.oop.demo06;

public interface TimeService {
void timer();
}

实现类

package com.Yaof.oop.demo06;
//类实现接口通过implemens
//实现接口中的类,就必须重写接口中的方法
public class UserserivceImpl implements Userservice,TimeService{
@Override
public void add(String name) {

}

@Override
public void delete(String name) {

}

@Override
public void update(String name) {

}

@Override
public void query(String name) {

}

@Override
public void timer() {

}

(八)内部类

1、成员内部类

在类里面创建类,可以访问私有属性

一个Java类中只能存在一个public类

package com.Yaof.oop.demo07;

public class Outer {

private int id = 10086;
public void out(){
System.out.println("我是外部类");
}
public class Inner{
public void in(){
System.out.println("我是内部类");
}
public void getid(){
System.out.println(id);
}
}
}
package com.Yaof.oop;

import com.Yaof.oop.demo07.Outer;

public class Application {
public static void main(String[] args) {
Outer outer = new Outer();//构造一个外部对象
outer.out();//调用外部方法
Outer.Inner inner= outer.new Inner();//构造一个内部对象
inner.in();//调用内部方法
inner.getid();//调用 内部调用外部属性 的方法
}
/*结果:
我是外部类
我是内部类
10086*/

}

2、静态内部类

package com.Yaof.oop.demo07;

public class Outer {

private int id = 10086;
public void out(){
System.out.println("我是外部类");
}
public static class Inner{
public void in(){
System.out.println("我是内部类");
}
/* public void getid(){
System.out.println(id);//static静态内部类不再可以调用外部私有属性,因为它会随着启动一起加载
}*/
}
}
package com.Yaof.oop;

import com.Yaof.oop.demo07.Outer;

public class Application {
   public static void main(String[] args) {
       Outer outer = new Outer();//构造一个外部对象
       outer.out();//调用外部方法
       new Outer.Inner().in();//调用静态内部类的方法
  }
           /*结果:
           我是外部类
           我是内部类
           */
}

3、局部内部类

在方法体中的类

package com.Yaof.oop.demo07;

public class Outer {

   private int id = 10086;
   public void out(){
       System.out.println("我是外部类");
  }
   public void inner(){
       class Inner{//局部内部类
           private int name;
      }
}
}

4、匿名内部类

没有创建对象的内部类

import java.sql.SQLOutput;

public class Outer {
   public static void main(String[] args) {
       new Inner().eat();//匿名内部类
  }
}

class Inner{
   public  void eat(){
       System.out.println("吃");
  }
}
4.1 lambda表达式

类名 对象名 = ( ) ->{ } ;

等价于新建了一个对象,而且构造了一个方法,只能构造一个方法

对接口和抽象类实现,主要用于接口匿名

十三、异常

(一)异常框架

image-20220513102258178

(二)异常基本知识

在Exception分支中有一个重要的子类RuntimeException(运行时异常)

  • ArrayIndexOutOfBoundsException(数组下标越界)

  • NullPointerException(空指针异常)

  • ArithmeticException(算术异常)

  • MissingResourceException(丢失资源)

  • ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。

这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;

Error和Exception的区别:

  • Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;

  • Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。

package com.Yaof.exception;

public class Demo01 {
public static void main(String[] args) {
int a = 1;
int b = 0;

try {
int c = a/b;
} catch (ArithmeticException x) {//catch 捕获异常
System.out.println("除数出错了");
// e.printStackTrace();
}try {
new Demo01().a();
}
catch (Error y){//Throwable为最大范围
System.out.println("方法出错了");
}
finally {
System.out.println("finally");
}
}
public void a(){
b();}
public void b(){
a();}
/*除数出错了
方法出错了
finally
*/
}
package com.Yaof.exception;
//抛出异常
public class Demo01 {
public static void main(String[] args) {
try {
new Demo01().add(2,0);
} catch (Exception e) {//捕获后程序可以正常运行
System.out.println("异常捕获了");
// e.printStackTrace();
} finally {
}
}
//假设方法中处理不了异常,就抛出异常
public void add(int a,int b) throws ArithmeticException{//抛出异常到上级
if (b==0){
System.out.println("异常抛出了");
throw new ArithmeticException();//主动抛出异常,一般在方法中使用
}
}
/* 结果:
异常抛出了
异常捕获了*/
}

(三)自定义异常

package com.Yaof.exception;
//自定义一个异常
public class MyExceotion extends Exception {
//传递数字大于5
private int detail;

public MyExceotion(int a) {//用构造器一个方法
this.detail = a;
}

//toString:异常的打印信息
@Override
public String toString() {
return "MyExceotion{" + "detail=" + detail + '}';
}
}
package com.Yaof.exception;

public class Test {
//可能存在异常的方法
static void test(int a) throws MyExceotion {
if(a>5){//大于5则作为异常抛出
throw new MyExceotion(a);//抛出
}
System.out.println("ok");
}

public static void main(String[] args) {
try {
test(5);//ok
test(10);//Myexception>>MyExceotion{detail=10}
} catch (MyExceotion e) {
System.out.println("Myexception>>"+e);
}
}
}

十四、枚举

package com.Yaof.exception;
public enum Status {
A,B,C;//直接写出枚举的名字
}
//在调用枚举时,直接把数据类型改为Status,例如 Status X; 定义了一个枚举x

十五、泛型

1. 基本使用:属性和方法

package com.Yaof.oop.T;

public class Score<T> {
String name;
String id;
T score;//score可以存放integer和String

public Score(String name, String id, T score) {
this.name = name;
this.id = id;
this.score = score;
}

public T getScore() {//若方法的返回值是泛型,系统会自动判断
return score;
}

public void setScore(T score) { //若方法的形式参数为泛型,那么实参也只能是泛型
this.score = score;
}

public <E> void test(E e){//泛型也可以用于方法定义前
System.out.println(e);
}
}
package com.Yaof.oop.T;

public class DemoT {
public static void main(String[] args) {
Score<String> score1 = new Score<String>("yaof","66","10");
String i = score1.score;
score1.test("yf666");//e是object类
}
}

2. 通配符"?"

package com.Yaof.oop.T;

public class DemoT {
public static void main(String[] args) {
Score<?> score1 = new Score<String>("yaof","66","10");//通配符"?"也就是object
String i = (String) score1.score;//强制转换
score1.test("yf666");//e是object类
}
}

3. 上、下界限

上界:

? extends Number:限定匹配Number类和它的子类

 

下界:

?super Integer:限定匹配Integer类和它的父类

 

package com.Yaof.oop.T;

public class DemoT {
   Integer x ;
   public static void main(String[] args) {
       //? extends Number:限定匹配Number类和它的子类
       //? super Integer:限定匹配Integer类和它的父类
       Score<? super Integer> score1 = new Score<Integer>("yaof","66",100);//通配符"?"也就是object
       System.out.println(score1.score);
       score1.test("yf666");//e是object类
       Number number =(Number) score1.getScore();
       System.out.println(number);

/*     100
       yf666
       100*/
  }
}

4. 反编译扩展

通过反编译,在终端中输入javap -l .\Score.class 找出score被限定上限后是Number类

image-20220613153420788

5. 钻石运算符<>

        Score<? extends Integer> score1 = new Score<>("yaof","66",100);//<>就是钻石运算符,更加简洁
//     Score<? extends Integer> score1 = new Score<Integer>("yaof","66",100);

6. 接口的泛型使用

package com.Yaof.oop.T;
//接口泛型 与 指定接口泛型
public class Score<T> implements ScoreInterface<T> {//泛型<T>
   private String name;
   private String id;

   public Score(String name, String id, T score) {
       this.name = name;
       this.id = id;
  }

   @Override
   public T getScore() {
       return null;
  }

   @Override
   public void setScore(T t) {

  }
}

class Score2 implements ScoreInterface<String> {//指定String
   //通过反编译可以发现,先是重写了object,再重写String,这就是桥接的方法
   private String name;
   private String id;

   public Score2(String name, String id) {
       this.name = name;
       this.id = id;
  }

   @Override
   public String getScore() {
       return null;
  }

   @Override
   public void setScore(String s) {

  }
}

十六、数据结构基础

1. 顺序表 ArrayList

package com.Yaof.oop.T;

/*
* 线性表的抽象类
* @param <E> 存储的元素(Element)类型
* */
public abstract class AbstractList <E>{

   /*
   * 获取表的长度
   *@return 顺序表的长度
   * */
   public abstract int size();

   /*
    * 添加一个元素
    * @param e 元素
    * @param index 要添加的位置(索引)
    * */
   public abstract int add(E e,int index);

   /*
    * 移除指定的位置元素
    * @param index 位置
    * @return 移除的元素
    * */
   public abstract E remove(int index);

   /*
    * 获取指定的位置元素
    * @param index 位置
    * @return 元素
    * */
   public abstract E get(int index);
}
package com.Yaof.oop.T;

public class ArrayList <E> extends AbstractList<E>{
   //底层数组
   private Object[] arr = new Object[2];
   //长度
   int size = 0;


   @Override
   public int size() {
       return 0;
  }

   @Override//插入、新增元素
   public int add(E e, int index) {
       if (index>size) throw new IllegalArgumentException("非法的插入");
       if(size >= arr.length){//扩容
           Object[] arr = new Object[this.arr.length+10];
           for (int i = 0; i < this.arr.length; i++) arr[i]=this.arr[i];
           this.arr = arr;
      }
       int i = size - 1;
       while (i>=index){//后移元素
           arr[i+1]=arr[i];
           i--;
      }
       arr[index]=e;//插入
       size++;
       for (Object o : this.arr) {
           if(o!=null)
               System.out.println(o);
      }
       return 0;
  }

   @Override//删除元素
   public E remove(int index) {
       if (index>size-1) throw new IllegalArgumentException("非法的删除");
       int i = index;
       E e = (E) arr[index];
       while (i<size-1){
           arr[i]=arr[i+1];
           i++;
      }
       size--;
       return e;
  }


   @Override//查找
   public E get(int index) {
       if (index>size-1) throw new IndexOutOfBoundsException("下标位置不存在");
       return (E) arr[index];
  }
}

2. 链表 linkedlist

package com.Yaof.oop.T;

public class LinkedList<E> extends AbstractList<E>{
   private Node<E> head = new Node<>(null);
   private int size;

   @Override
   public int size() {
       return size;
  }

   @Override
   public void add(E e, int index) {
       if (index>size) throw new IllegalArgumentException("非法的插入");//判断位置是否合法
       Node<E> node = head,temp;
       for (int i = 0; i < index; i++) node = node.next;//这里找到前驱节点位置,即node
       temp = node.next;//将前驱节点的原后驱节点存放到temp
       node.next = new Node<>(e);//插入新的节点
       node.next.next = temp;//新插入节点的后驱节点
       size++;
  }

   @Override
   public E remove(int index) {
       if (index>size) throw new IllegalArgumentException("非法的插入");//判断位置是否合法
       Node<E> node = head,temp;
       for (int i = 0; i < index; i++) node = node.next;//这里找到前驱节点位置,即node
       temp = node.next;
       node.next=node.next.next;//将删除节点的后驱节点存放到删除节点
       size--;
       return temp.e;
  }

   @Override
   public E get(int index) {
       if (index>size) throw new IllegalArgumentException("非法的插入");//判断位置是否合法
       Node<E> node = head.next;
       for (int i = 0; i < index; i++) node = node.next;//这里找到前驱节点位置,即node
       return node.e;
  }

   private static class Node<E>{//创建链表
       private E e;
       private Node<E> next;//定义链表的后驱节点

       public Node(E e) {
           this.e = e;
      }
  }
}

3.小结

3.1 顺序表优缺点:

  • 访问速度快,随机访问性能高

  • 插入和删除的效率低下,极端情况下需要变更整个表

  • 不易扩充,需要复制并重新创建数组

3.2 链表优缺点:

  • 插入和删除效率高,只需要改变连接点的指向即可

  • 动态扩充容量,无需担心容量问题

  • 访问元素需要依次寻找,随机访问元素效率低下

 

4.栈 stack(出、入栈)

先入后出,像水杯一样

package com.Yaof.oop.Abstract;
/*
* 抽象类 栈,待实现
* @param <E> 元素类型
* */
public abstract class AbstractStack <E>{
   /*
   * 出栈
   * @return 栈顶元素
   */
   public abstract E pop();

   /*
    * 入栈
    * @param e 元素
    */
   public abstract void push(E e);
}
package com.Yaof.oop.Abstract;
//实现出栈pop 和 入栈push
public class ArrayStack<E> extends AbstractStack<E>{
   //底层数组
   private Object[] arr = new Object[2];
   //长度
   int size = 0;
   @Override
   public E pop() {
       return (E) arr[(size--)-1];
  }

   @Override
   public void push(E e) {
       if(size >= arr.length){//扩容
           Object[] arr = new Object[this.arr.length+10];
           for (int i = 0; i < this.arr.length; i++) arr[i]=this.arr[i];
           this.arr = arr;
      }
       arr[size++]=e;
  }
}
package com.Yaof.oop;

import com.Yaof.oop.Abstract.ArrayStack;
import com.Yaof.oop.T.AbstractList;
import com.Yaof.oop.T.LinkedList;

public class Application {
   public static void main(String[] args) {
       ArrayStack<String> stack = new ArrayStack<>();
       stack.push("A");
       stack.push("B");
       stack.push("C");
       System.out.println(stack.pop());
       System.out.println(stack.pop());
       stack.push("D");
       System.out.println(stack.pop());
       System.out.println("demo");
  };
   /*结果:
   * C
   * B
   * D
   * demo
   * */
}

5. 队列queue(进、出队列)

package com.Yaof.oop.Abstract;
/*
* 抽象类 队列,待实现
* @param <E> 元素类型
* */
public abstract class  AbstractQueue<E> {
       /*
        * 进队
        * @return 元素
        */
       public abstract void offer(E e);

       /*
        * 出队
        * @param e 元素
        */
       public abstract E poll();
}
package com.Yaof.oop.Abstract;

public class ArrayQueue<E> extends AbstractQueue<E>{
   //底层数组
   private Object[] arr = new Object[4];
   //队列首尾
   private int head = 0,tail = 0;
   @Override
   public void offer(E e) {//队尾进队
       int next = (tail+1) % arr.length;//新的队尾,取余法,控制新队尾在length内
       if (next==head) return;//防止溢出
       arr[tail] = e;
       tail=next;
  }

   @Override
   public E poll() {//队首出队
       E e = (E) arr[head];
       head = (head+1) % arr.length;//控制新队首在length内
       return e;
  }
}

6. 二叉树和三种遍历

image-20220615160038242

package com.Yaof.oop.Abstract;
//二叉树
public class TreeNode<E>{
   public E e;
   public TreeNode<E> left;
   public TreeNode<E> right;
}
  • 前序遍历:从二叉树的根结点出发,到达结点时就直接输出结点数据,按照先向左在向右的方向访问。ABCDEF

  • 中序遍历:从二叉树的根结点出发,优先输出左子树的节点的数据,再输出当前节点本身,最后才是右子树。CBDAEF

  • 后序遍历:从二叉树的根结点出发,优先遍历其左子树,再遍历右子树,最后在输出当前节点本身。CDBFEA

package com.Yaof.oop;

import com.Yaof.exception.Test;
import com.Yaof.oop.Abstract.TreeNode;

public class Application {
   public static void main(String[] args) {
       TreeNode<String> root = new TreeNode<>("A");
       root.left=new TreeNode<>("B");
       root.right=new TreeNode<>("E");
       root.left.left=new TreeNode<>("C");
       root.left.right=new TreeNode<>("D");
       root.right.right=new TreeNode<>("F");
       test(root);
  };
   public static void test(TreeNode<String> root){
       if(root==null) return;//若该节点为空,则返回,我的理解为结束了当前节点
       System.out.print(root.e+" ");//前序遍历:先中再左最后右 ABCDEF
       test(root.left);
       //System.out.print(root.e+" ");//中序遍历:先左再中最后右 CBDAEF
       test(root.right);
       //System.out.print(root.e+" ");//后序遍历:先左后右最后中 CDBFEA
  }
   /*结果:
   * */
}

满二叉树:满满的二叉树,每一层都是满节点

完全二叉树:最底层的叶子节点可以不满,但是得靠左排布

7. 哈希表

结合了顺序表和链表,用顺序表来做链表的头节点

image-20220615162531129

8.二叉排序树

每个节点的左子树一定小于本身,右子树一定大于本身,算法复杂度是log 2

image-20220615163551363

9.平衡二叉树

要求左、右子树的高度差绝对值不超过1

image-20220615171648465

image-20220615172006720

10.红黑树

红黑树的特性:

  1. 每个节点或者是黑色,或者是红色。

  2. 根节点是黑色。

  3. 每个叶子节点的两边也需要表示(虽然没有,但是null也需要表示出来)是黑色。

  4. 如果这个节点是红色的,则它的子节点必须是黑色的。

  5. 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

基本的插入规则和平衡二叉树一样,但是在插入后:

1.将新插入的节点标记为红色

2.如果x是根结点(root),则标记为黑色

3.如果X的parent不是黑色,同时X也不是root:

3.1 如果X的uncle(叔叔)是红色

  • 将parent和uncle标记为黑色

  • 将grand parent(祖父) 标记为红色

  • 让X节点的颜色与X祖父的颜色相同,然后重复步骤2、3

3.2 如果 X 的 uncle (叔叔) 是黑色,我们要分四种情况处理

  • 左左(P是G的左孩子,并且X是P的左孩子)

  • 左右(P是G的左孩子,并且X是P的右孩子)

  • 右右(P是G的右孩子,并且X是P的右孩子)

  • 右左(P是G的右孩子,并且x是P的左孩子)

其实这种情况下处理就和我们的平衡二叉树一样了

十七、集合

image-20220615202121541

1.Collection

数组与集合

相同之处: 1.它们都是容器,都能够容纳一组元素。

不同之处:

1.数组的大小是固定的,集合的大小是可变的。 2.数组可以存放基本数据类型,但集合只能存放对象。 3.数组存放的类型只能是一种,但集合可以有不同种类的元素。

1.1 ArrayList

用了泛型为String和自建的Student相对比,若不重写equals方法,contains将返回false

package com.Yaof.oop.collection;

import java.util.ArrayList;
import java.util.List;

public class ArrayListTest {
   public static void main(String[] args) {
       //系统自带的String
       List<String> list = new ArrayList<>(200);//设置容量为200
       list.add(0,"A");
       list.add(1,"B");
       list.add("C");
       System.out.println(list);
       System.out.println(list.contains("A"));//是否包含A,源码调用了equals方法
       System.out.println(list.remove(2));//删除C

       //新建的Student类,仅有属性String name和有参构造,重写了equals方法
       List<Student> list1 = new ArrayList<>(200);//设置容量为200
       list1.add(new Student("A"));
       list1.add(new Student("B"));
       System.out.println(list1.contains(new Student("A")));//这里如果Student类不重写equals方法,结果就是false

       //批量操作
       list1.addAll(new ArrayList<>());//在尾部批量插入元素
       list1.removeAll(new ArrayList<>());//批量移除给定集合中有的元素
       list1.retainAll(new ArrayList<>());//只保留给定集合中的元素
  }
/*   [A, B, C]
     true
     C
     true*/
}

1.2 LinkList

package com.Yaof.oop.collection;

import java.util.LinkedList;
//链表的基操、队列、栈
public class LinkListTest {
   public static void main(String[] args) {
       LinkedList<Object> list = new LinkedList<>();

       list.add("a");

       list.offer("b");//入队,源码也是用的add方法
       System.out.println(list.poll());//出队
       System.out.println(list.poll());//出队
       System.out.println("------------------");

       list.push("A");//入栈
       list.push("B");
       list.push("C");
       System.out.println(list.pop());//出栈
       System.out.println(list.pop());
       System.out.println(list.pop());
  }
   /*结果:
     a
   * b
   * --------------
   * C
   * B
   * A
   * */
}
package com.Yaof.oop.collection;

import java.util.Comparator;
import java.util.LinkedList;
//链表的排序
public class LinkListTest2 {
   public static void main(String[] args) {
       LinkedList<Integer> list = new LinkedList<Integer>(){{
           this.add(2);
           this.add(3);
           this.add(1);
      }};
       list.sort(new Comparator<Integer>() {//排序操作
           @Override
           public int compare(Integer o1, Integer o2) {//返回值小于0则o1在o2前面,否则反之
               return o1-o2;
          }
      });
       System.out.println(list);//[1,2,3]
  }
}

1.3 迭代器Integer

几种常见的遍历以及Integer:

package com.Yaof.oop.collection;

import java.util.LinkedList;
import java.util.ListIterator;
import java.util.function.Consumer;

//迭代器Integer
public class LinkListTest2 {
   public static void main(String[] args) {
       LinkedList<Integer> list = new LinkedList<Integer>(){{
           this.add(1);
           this.add(2);
           this.add(3);
      }};
/*       list.forEach(new Consumer<Integer>() {//函数式接口Consumer<T>(消费型),可用lambda表达式 ------第一种
           @Override
           public void accept(Integer integer) {//需要重写accept方法
               System.out.println(integer);
           }
       });
       list.forEach(System.out::println);//用println替换了accept,等价于accept方法 ------第二种
       */
       for (Integer integer : list) {//加强for循环 1 2 3 ----------第三种
           System.out.print(integer+" ");
      }
       System.out.println(list);//直接输出 [1,2,3] ----------第四种

       //第五种,迭代器
       ListIterator<Integer> iterator = list.listIterator();//新建一个迭代器
       while (iterator.hasNext()){//顺序输出
           Integer i = iterator.next();
           System.out.println(i);
      }
       System.out.println("----------");
       while (iterator.hasPrevious()){//逆序输出,previous(之前的)
           Integer i = iterator.previous();
           System.out.println(i);
      }
  }
}

1.4 Set

package com.Yaof.oop.collection;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;

public class SetTest {
   public static void main(String[] args) {
//     Set<Integer> set = new HashSet<>();//HashSet,不支持插入指定位置
       Set<Integer> set = new LinkedHashSet<>();//会保存插入顺序
       set.add(120);
       set.add(13);
       set.add(11);
       for (Integer integer : set) {//遍历
           System.out.println(integer);
      }

       TreeSet<Integer> set1 = new TreeSet<>();//红黑树,默认顺序输出1,2,3
//     TreeSet<Integer> set1 = new TreeSet<>((a,b)->b-a);//源码有Comparator接口,此时输出3,2,1
       set1.add(1);
       set1.add(3);
       set1.add(2);
       System.out.println(set1);
  }
}

1.5 HashMap

image-20220618171932750

哈希表的本质: 是一个用于存放后续节点的头结点的数组,数组里面的每一个元素都是一个头结点(也可以说就是一个链表)

当要新插入一个数据时,会先计算该数据的哈希值,找到数组下标,然后创建一个新的节点,添加到对应的链表后面。

    /**
    * The table, initialized on first use, and resized as
    * necessary. When allocated, length is always a power of two.
    * (We also tolerate length zero in some operations to allow
    * bootstrapping mechanics that are currently not needed.)
    */
   transient Node<K,V>[] table;//K是Key,V是Value

/**
* The default initial capacity - MUST be a power of two.
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 初始值为16,每次扩容都是2的倍数

   /**
    * The load factor used when none specified in constructor.
    */
   static final float DEFAULT_LOAD_FACTOR = 0.75f;//LoadFactor负载因子,默认值0.75,数组占用达到HashMap的75%时就扩容

因为链表过长问题的发生,JDK1.8引入了红黑树的数据结构:

当链表长达到8时,就自动将链表转换为红黑树

1.6 LinkedHashMap

package com.Yaof.oop.collection;

import java.util.HashMap;
import java.util.LinkedHashMap;

public class HashMapTest {
   public static void main(String[] args) {
//     HashMap<Integer, String> map = new HashMap<>();//无序

       //LinkedHashMap有序,因为有before,after
       //accessOrder若为true,则被访问的键值对会被放置到最后
       HashMap<Integer, String> map = new LinkedHashMap<>(16,0.75f,true);
       map.put(1,"A");//新增键值对1,元素A
       map.put(3,"C");
       map.put(4,"D");
       map.put(2,"B");
       map.get(3);//访问键值对3,并置后
       map.get(2);
       map.get(1);
       System.out.println(map);//{4=D, 3=C, 2=B, 1=A}
  }
}

1.7 TreeMap

package com.Yaof.oop.collection;
import java.util.TreeMap;

public class TreeMapTest {
   public static void main(String[] args) {
       TreeMap<Integer, String> map = new TreeMap<>((a,b)->b-a);//这里有个comparator比较,默认Key输出1,2,3,这里反之
       map.put(1,"A");//新增键值对1,元素A
       map.put(3,"C");
       map.put(2,"B");
       System.out.println(map);//{ 3=C, 2=B, 1=A}
  }
}

1.8 HashMap实操

package com.Yaof.oop.collection;

import java.util.HashMap;

public class HashMapTest2 {
   public static void main(String[] args) {
       HashMap<Integer, String> map = new HashMap<>(16,0.75f);
       map.put(1,"A");//新增键值对1,元素A
       map.put(3,"C");
       map.put(2,"B");
       System.out.println(map.get(1));
       System.out.println(map.getOrDefault(0,"K"));//如果Key不存在,则返回后面的值
//     map.remove(1);//删除
       System.out.println(map);
       System.out.println("------------");
       map.forEach((k, v) -> System.out.println(k+"->"+v));//用foreach打印k->v
/*       //与上方相同效果
       for (Map.Entry<Integer, String> entry : map.entrySet()) {
           int key = entry.getKey();
           String value = entry.getValue();
           System.out.println(key+"->"+value);
       }*/

  }
   /*A
     K
     {1=A, 2=B, 3=C}
     ------------
     1->A
     2->B
     3->C*/
}
 
posted @ 2022-06-20 08:45  爱吃蘋果  阅读(80)  评论(0)    收藏  举报