Java基础知识(纯干货)

基础篇

IDEA 开发 Java项目


卸载JDK

  1. 删除Java的安装目录

  2. 删除JAVA_HOME

  3. 删除path下关于java的目录

  4. java -version

安装JDK17

  1. 下载链接:https://download.oracle.com/java/17/archive/jdk-17.0.1_windows-x64_bin.exe

  2. 设置环境变量

    1. 在我的电脑->高级系统设置新建变量 JAVA_HOME,变量值为 E:\Java (此处填写自己的安装路径)
    2. 新建CLASSPATH 变量值为 %JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
    3. 在Path中新增变量 ---    %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
    4. 测试是否安装成功 --- 在控制台输入 java 或者 java -version 不报错就可以了

安装JDK 8

  1. 百度搜索JDK8,找到下载地址

  2. 同意协议

  3. 下载对应版本

  4. 记住安装路径

  5. 配置环境变量

    • 我的电脑-->右键-->属性-->高级系统设置

    • 环境变量-->系统变量-->JAVA_HOME

    • 配置Path变量----> %JAVA_HOME%\bin

      %JAVA_HOME%\jre\bin

  6. 测试是否安装成功


IDEA 代码快捷键

  1. psvm 生成main方法

  2. sout 输出 System.out.println(); 语句

  3. Ctrl + D :复制当前行到下一行

  4. alt + insert :会生成构造器(构造方法)

  5. Ctrl + H :显示类结构图

  6. 快捷键 : Ctrl + ALT + T ---> 选择代码块进行包裹代码(如:if/else , try/catch......)

  7. maven导依赖,浏览器直接搜 maven + mysql / standard 等等


Java语法

注释

  1. 单行注释: //

  2. 多行注释: /* 注释内容*/ , 可以注释一段文字

  3. 文档注释:(JavaDoc) /** 注释内容 */

 

标识符

  1. 标识符大小写敏感

  2. 应以字母、美元符、下划线开始

  3. 不可使用关键字作为变量名或方法名


数据类型

  • 注意:

    1. long 类型要在数字后面加个L

    2. float类型要在数字后面加个F

    3. String 用来定义字符串,String不是关键字

    4. 布尔型:

      • boolean flag = true; boolean flag = false;

 


什么是字节

位(bit):是计算机 内部数据 存储的最小单位,11001100是一个八位二进制数。

字节(byte):是计算机中 数据处理 的基本单位,习惯上用大写B来表示。

字符:是指计算机中使用的字母、数字、字和符号

1 bit 表示1位 1Byte表示一个字节---> 1B(byte) = 8 bit

1024B=1KB 1024KB=1M 1024M=1G 1024G=1TB

 


数据类型扩展

 


字符扩展

 //所有的字符本质还是数字
 //编码 Unicode 表: (97 = a 65 = A) 2字节   0-65536     Excel 2的16次方 = 65536
 //U0000   UFFFF
 char c3 = '\u0061';
 System.out.println(c3);
 //转义字符     \t-->制表符       \n-->换行
 System.out.println("Hello\nWorld!");
 
 System.out.println("=================================================");
 String sa = new String("hello world");
 String sb = new String("hello world");
 System.out.println(sa==sb);                     //false
 
 String sc = "hello world";
 String sd = "hello world";
 System.out.println(sc==sd);             //true
 
 //对象 从内存分析
 
 //布尔值扩展
 boolean flag = true;
 if (flag==true){ }    //新手
 if (flag){ }        //老手
 //Less is More!   代码要精简易读

 


类型转换

  1.  //强制转换    (类型)变量名    高--低
     int i = 128;
     byte b = (byte)i;
     System.out.println(i);     //128
     System.out.println(b);      // -128
  2.  //自动转换    低--高
     int m = 128;
     double n = m;
     System.out.println(m);      //128
     System.out.println(n);      //128.0
  3. 注意:

    • 不能对布尔值进行转换

    • 不能把对象类型转换为不相干的类型

    • 在把高容量转换为低容量的时候,强制转换

    • 转换的时候可能存在内存溢出,或者精度问题

  4.  char c = 'a';
     int d = c+1;
     System.out.println(d);    // 98
     System.out.println((char) d);    // b
  5.  public static void main(String[] args) {    
     //操作数比较大的时候,注意溢出问题    
     //JDK7新特性,数字之间可用下划线分割    
     int money = 10_0000_0000;    int years = 20;    
     int total = money * years;   // -1474836480 , 计算的时候溢出了    
     long total2 = money * years;  //默认是int,转换之前已经存在问题    
     long total3 = money*((long)years);  //先把一个数转换为 long  
     System.out.println(total3);     //20000000000
     }

 


变量

  1. Java是一种强类型语言,每个变量都必须声明其类型。类型可以是基本类型,也可以是引用类型。

  2. Java变量是程序中最基本的存储单元,其要素包括变量名、变量类型和作用域。

  3. 变量名必须是合法的标识符。

变量作用域

1. 类变量 2.实例变量 3.局部变量

 public class Variable {    
  static int allClicks = 0;   //类变量
  String str = "Hello world";    //实例变量
     
  public void method(){        
    int i = 0;     //局部变量    
  }
 }

 

变量使用---示例

public class Demo04 {     
     
     //类变量   static    
     static double salary = 2500;   
     
     //属性:变量    
     
     //实例变量:从属于对象;  如果不进行初始化,则输出该类型的默认值    
     //布尔值:默认是false    
     //除了基本类型,其余的默认值都是null    
     String name;    
     int age;    
     
     //main方法    
     public static void main(String[] args) {     
         
         //局部变量-->必须声明和初始化值        
         int i = 10;        
         System.out.println(i);   
         
         //实例变量:对应上面的内容        
         //变量类型   变量名字 = new Demo04();        
         Demo04 demo04 = new Demo04();        
         System.out.println(demo04.age);        
         System.out.println(demo04.name); 
         
         //类变量 static        
         System.out.println(salary);                 
     }        
     //其他方法    
     public void add(){    }
 }

 

变量的命名规范

  1. 类成员变量:首字母小写和驼峰原则:除了第一个单词以外,后面的单词首字母大写。如:monthSalary.

  2. 局部变量:首字母小写和驼峰原则

  3. 常量:大写字母和下划线:MAX_VALUE

  4. 类名:首字母大写和驼峰原则:Man,GoodMan

  5. 方法名:首字母小写和驼峰原则:run(),runRun()

 


常量

  1. 常量名一般使用大写字符。

  2. 格式: final 常量名 = 值 ; 例: final double PI = 3.14 ;

  3. 修饰符(数据类型前的内容,如示例中的 static 和 final ),不存在先后顺序。

    static final double PI = 3.14;

    final static double PI = 3.14; 输出内容相同。


运算符

  1. 数据类型没有 long 时,所有 非int 类型转为 int 型:

1  public static void main(String[] args) {    
2      long a = 1234569653412L;    
3      int b = 123;    
4      short c = 10;    
5      byte d = 8;    
6      System.out.println(a+b+c+d);   //结果为 Long 型    
7      System.out.println(b+c+d);     //结果为 Int 型    
8      System.out.println(c+d);    //结果为 Int 型
9  }

 

  1. 运算结果的数据类型为参与运算的变量中最高优先级的数据类型。

  2. 关系运算符返回的结果为:正确 / 错误 布尔值

幂运算

------借助Math类

 //幂运算  2^3   2*2*2=8
 double pow = Math.pow(2,3);
 System.out.println(pow);   // 8.0

位运算符

  1. & | ^ ~

 //位运算符
 /** A = 0011 1100
 * B = 0000 1101
 * -------------------
 * A&B = 0000 1100
 * A|B = 0011 1101
 * A^B = 0011 0001
 * ~B = 1111 0010*
 */
  1. << 相当于 * >> 相当于 /

 

三元运算符

格式: x ? y : z 如果 x==true,则结果为 y,否则结果为 z

 int score = 50;
 String type = score < 60 ? "不及格":"及格";
 System.out.println(type);      // 结果为 不及格

运算符优先级

优先级描述运算符
1 括号 ()、[]
2 正负号 +、-
3 自增自减,非 ++、--、!
4 乘除,取余 *、/、%
5 加减 +、-
6 移位运算 <<、>>、>>>
7 大小关系 >、>=、<、<=
8 相等关系 ==、!=
9 按位与 &
10 按位异或 ^
11 按位或 |
12 逻辑与 &&
13 逻辑或 ||
14 条件运算 ? :
15 赋值运算 =、+=、-=、*=、/=、%=
16 位赋值运算 &=、|=、<<=、>>=、>>>=、

字符串连接符 +

int m = 10;
 int n = 20;
 //字符串连接符 +
 System.out.println(""+m+n);     // 结果为 1020
 System.out.println(m+n+"");   // 结果为 30

 


JavaDoc生成文档

1. 在IDEA中生成一个Javadoc文档

  1. 首先新建一个文件夹,用于存放要生成的Javadoc文档;

  2. 点击 IDEA 顶部的Tools菜单,选择Generate JavaDoc选项;

  3. 然后在弹出界面,点击 Output directory 输入框后面的按钮,选择刚才新建的文件夹;

  4. 在底部的Locale输入框配置语言和编码集,语言用zh_CN,代表中文

    -encoding utf-8 -charset utf-8

  5. 点击确定后,等待 IDEA 生成JavaDoc文档即可,

  6. 接下来打开JavaDoc文件夹,找到index.html文件,点击就能看到API文档。

2. 在IDEA中生成一个Javadoc文档

参见 https://blog.csdn.net/Joy_Roy6/article/details/123028798 (Ctrl+鼠标左键)

 


Java流程控制

Scanner对象

  1. 可以通过Scanner类来获取用户的输入。

  2. 基本语法: Scanner s = new Scanner (System.in);

  3. 通过 Scanner 类的 next() 与 nextLine() 方法获取输入的字符串,在读取前我们一般需要使用 hasNext() 与hasNextLine() 判断是否还有输入的数据。

  4. next() 与 nextLine() 的区别:

  1. next方式:

 1 public static void main(String[] args) {    
 2      //创建一个扫描器对象,用于接收键盘数据    
 3      Scanner scanner = new Scanner(System.in);   //程序会等待用户输入完毕 
 4      
 5      System.out.println("使用next方式接收:");    //判断用户有没有输入字符串   
 6      
 7      if (scanner.hasNext()){        
 8          //使用next方式接收        
 9          String str = scanner.next();        
10          System.out.println("输入的内容为:"+str);    
11      }    
12      //凡是属于IO流的类,如果不关闭,会一直占用资源    
13      scanner.close();
14  }

 

  1. 也可以通过不使用 if() 判断,来获取用户输入的内容:

1  public static void main(String[] args) {   
2      Scanner scanner = new Scanner(System.in);    
3      System.out.println("请输入数据:");    
4      
5      String str = scanner.nextLine();    
6      System.out.println("输出的内容为:"+str);    
7      
8      scanner.close();
9  }
  1. 小例子:

 
 1 public static void main(String[] args) {    
 2      //输入多个数字,并求其总和与平均数,    
 3      //每输入一个数字用回车键确认,通过输入非数字来结束输入并输出执行结果    
 4      Scanner scanner = new Scanner(System.in);    
 5      //
 6      double sum = 0;    
 7      //计算输入了多少个数字    
 8      int m = 0;    
 9      //通过循环判断是否还有输入,并在里面对每一次进行求和与统计    
10      while(scanner.hasNextDouble()){        
11          double x = scanner.nextDouble();        
12          m = m + 1;          
13          sum = sum + x;        
14          System.out.println("你输入了第"+m+"个数据,当前结果sum="+sum);    
15      }    
16      System.out.println(m + "个数的和为" + sum);    
17      System.out.println(m + "个数的平均值是" + (sum / m));    
18      scanner.close();
19  }

 


顺序结构

选择结构

1. if 选择结构

2. switch 多选择结构

  • Switch case 语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。

  • Switch 语句中的变量类型可以是 byte, short, int 或char,String , 同时case 标签必须为字符串常量或字面量。

 1  switch (){    
 2      case value :        
 3          //语句        
 4          break;   //可选    
 5      case value :        
 6          //语句        
 7          break;   //可选    
 8          //可以有任意数量的case语句    
 9      default : //可选        
10          //语句
11  }

循环结构

1. while 循环

while 是最基本的循环,它的结构为:

 while(布尔表达式){    
     //循环内容
 }
  • 只要布尔表达式为true,循环就会一直执行下去。

  • 下面代码计算 1+2+3+...+100:

1  public static void main(String[] args) {    
2      int i = 0;    
3      int sum = 0;    
4      while (i<=100){        
5          sum = sum + i;        
6          i++;    
7      }    
8      System.out.println(sum);
9  }

2. do...while 循环

do...while 循环和 while 循环相似,不同的是,do...while循环至少会执行一次。

 do {    
     //代码语句
 }while(布尔表达式);
  • 下面代码计算 1+2+3+...+100:

1  public static void main(String[] args) {    
2      int i = 0;    
3      int sum = 0;    
4      do {        
5          sum = sum + i;        
6          i++;    
7      }while(i<=100);    
8      System.out.println(sum);
9  }

3. For循环

  • for 循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。

  • for 循环执行的次数是在执行前就确实的。

  • 语法格式如下:

 for (初始化;布尔表达式;更新){    
     //代码语句
 }
  • 练习:输出1-1000之间能被5整除的数,并且每行输出3个

 
 1 public static void main(String[] args) {    
 2      for (int i = 0; i <= 1000; i++) {        
 3          if(i%5==0){            
 4              System.out.print(i+"\t");        
 5          }        if (i%(5*3)==0){ //每行            
 6              System.out.println();            
 7              //System.out.println("\n");        
 8          }    
 9      }
10  }

 

  • 练习:打印九九乘法表

 //1.先打印第一列
 //2.把固定的1再用一个循环包起来
 //3.去掉重复项,i <= j
 //4.调整样式
1 public static void main(String[] args) {    
2      for (int j = 1; j <= 9; j++) {        
3          for (int i = 1; i <= j; i++) {            
4              System.out.print(j+"*"+i+"="+(j*i) + "\t");        
5          }        
6          System.out.println();    
7      }
8  }

 

4.增强for循环

  • 语法格式:

 for(声明语句:表达式){    
     //代码句子
 }
  • 声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。

  • 表达式:表达式是要访问的数组名,或者是返回值为数组的方法。

  • 练习:遍历数组元素---以下为两种方法,法一为普通for循环,法二为增强for循环。

 1 public static void main(String[] args) {    
 2     int [] numbers = {10,20,30,40,50};   //定义了一个数组    
 3     
 4     for (int i = 0; i < 5; i++) {        
 5         System.out.println(numbers[i]);    
 6     }        
 7     System.out.println("-----------------------------------------------------");    
 8     //遍历数组的元素    
 9     for(int x:numbers){        
10         System.out.println(x);    
11     }
12 }

 


break 与 continue

  1. break 用于强行退出循环,不执行循环中剩余的语句。( break 语句也在switch 语句中使用)。

    break 在任何循环语句的主体部分,均可用 break 控制循环的流程。

  2. continue 语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。


流程控制练习

打印三角形

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 j = 1; j <= i ; j++) {            
            System.out.print("*");        
        }        
        for (int j = 1; j < i; j++) {            
            System.out.print("*");        
        }        
        System.out.println();    
    }
}

Debug的使用

 


Java 方法详解

方法的定义

  1. Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段。

  2. 一般情况下,定义一个方法包含以下语法:方法包含一个方法头和一个方法体。

  3. 定义方法的格式:

修饰符  返回值类型  方法名(参数类型 参数名){    
    ...    
    方法体            
    ...    
    return 返回值;
}
public class Demo01 {    
    //main方法    
    public static void main(String[] args) {     
        //实际参数:实际调用传递给他的参数
        int sum = add(1, 2);    //下面的add方法被static修饰时,main方法才可调用add() 
        System.out.println(sum);    }    
    //加法    
    //形式参数,用来定义作用的
    public static int add(int a,int b){        
        return a+b;    
    }
}

方法调用

  1. 调用方法:对象名.方法名(实参列表)

  2. 若是 static 即为静态方法,可以直接通过类名来调用;

    • 举例:

  3.  

    若为非静态方法,先用 new 实例化该类,然后进行调用;

    • 举例:

     

  4. 两种调用方法的方式:

  • 当返回一个值的时候,方法调用通常被当作一个值。例如:int larger = max(30, 40);

  • 如果方法返回值是void,方法调用一定是一条语句。如:System.out.println("Hello,World!");


方法的重载

  1. 定义:方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数类型或参数的个数

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

  3. 方法重载的规则:

  • 方法名称必须相同;

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

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

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


可变参数

  1. 在方法声明中,在指定参数类型后加一个省略号(...)。

  2. 一个方法只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。

 1 public class Demo04 {    
 2     public static void main(String[] args) {        
 3         //调用可变参数的方法        
 4         printMax(34, 3, 3, 2, 66.6,68.68);        
 5         printMax(new double[]{1,2,3});    }    
 6     public static void printMax(double... numbers){        
 7         if(numbers.length == 0) {            
 8             System.out.println("No argument passed");            
 9             return;        
10         }        
11         double result = numbers[0];        
12         //排序!        
13         for (int i = 1;i < numbers.length; i++){            
14             if(numbers[i] > result){                
15                 result = numbers[i];            
16             }        
17         }        
18         System.out.println("The max value is " + result);    
19     }
20 }

 


递归(笔试高频问点)

  1. 递归就是:A方法调用A方法,即自己调用自己。

  2. 递归结构包括两个部分:

  • 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。

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

 1 public class Demo06 {    
 2     //递归思想    
 3     //求阶乘 5! 5*4*3*2*1    
 4     public static void main(String[] args) {        
 5         System.out.println(f(5));    
 6     }    
 7     public static int f(int n){        
 8         if (n == 1){            
 9             return 1;        
10         }else {            
11             return n * f(n-1);        
12         }    
13     }
14 }

 


数组

数组的定义

  1. 数组是相同类型数据的有序集合。

  2. 相同类型的若干个数据,按照一定的先后次序排列组合而成。

  3. 每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。

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

  5. 数组长度是确定的,不可变得。如果越界,则报错:ArrayIndexOutOfBoundsException

数组的声明创建

  1. 首先必须声明数组变量,才能在程序中使用数组。

  2. 声明数组变量的语法如下:dataType[] arrayRefVar;

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

    dataType[] arrayRefVar = new dataType[arraySize];

  4. 数组的元素是通过索引访问的,数组索引从0开始。

  5. 获取数组长度: arrays.length

 1 public class ArrayDemo01 {    
 2     //变量的类型  变量的名字  =  变量的值    
 3     //数组类型    
 4     public static void main(String[] args) {        
 5         int[] nums;  //1.声明一个数组        
 6         nums = new int[10];  //2.创建一个数组        
 7         //上面两句也可合并为一句:int[] nums2 = new int[10];        
 8         //3.给数组元素中赋值        
 9         nums[0] = 1;        nums[1] = 2;        
10         nums[2] = 3;        nums[3] = 4;        
11         nums[4] = 5;        nums[5] = 6;        
12         nums[6] = 7;        nums[7] = 8;        
13         nums[8] = 9;        nums[9] = 10;        
14         //计算所有元素的和        
15         int sum = 0;        
16         for (int i = 0; i < nums.length; i++) {            
17             sum = sum + nums[i];        
18         }        
19         System.out.println("总和为:"+ sum);    
20     }
21 }

 

数组的三种初始化

静态初始化

int[] a = {1,2,3};

Man[] mans = {new Man(1,1),new Man(2,2)};

动态初始化

int[] a = new int[2]; a[0]=1; a[1]=2;

数组的默认初始化

数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。

 1 public class ArrayDemo02 {    
 2     public static void main(String[] args) {        
 3         //静态初始化:创建 + 赋值        
 4         int[] a = {1,2,3,4,5,6,7,8};        
 5         System.out.println(a[0]);        
 6         //动态初始化:包含默认初始化        
 7         int[] b = new int[10];       
 8         b[0] = 10;        
 9         System.out.println(b[0]);    
10     }
11 }

 


数组的使用

  1. 普通的for循环

  2. For-Each循环

  3. 数组作方法入参

  4. 数组作返回值

 1 public class ArrayDemo04 {    
 2     public static void main(String[] args) {        
 3         int[] arrays = {1,2,3,4,5};        
 4         //增强的for循环        
 5         //for (int array : arrays) {        
 6         //    System.out.println(array);        
 7         //}        printArray(arrays);        
 8         int[] reverse = reverse(arrays);       
 9         printArray(reverse);    
10     }    
11     //打印数组元素    
12     public static void printArray(int[] arrays){        
13         for (int i = 0; i < arrays.length; i++) {            
14             System.out.println(arrays[i]+"");        
15         }    
16     }    
17     
18     //反转数组---即倒序输出数组元素    
19     public static int[] reverse(int[] arrays){        
20         int[] result = new int[arrays.length];        
21         //反转的操作        
22         for (int i = 0, j = result.length-1; i < arrays.length; i++,j--) {           
23             result[j] = arrays[i];        
24         }        
25         return result;    
26     }
27 }

 

多维数组

多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其中每个元素都是一个一维数组。

二维数组

int a[][] = new int[3][5]; 解析:以上二维数组a可以看成一个三行五列的数组。

 1 public class ArrayDemo05 {    
 2     public static void main(String[] args) {        
 3         //[4][2]        
 4         int[][] array = {{1,2},{2,3},{3,4},{4,5}};        
 5         System.out.println(array[0][0]);        
 6         System.out.println(array[0][1]);        // 1 2
 7         System.out.println("================");        
 8         System.out.println(array.length);        // 4
 9         System.out.println(array[0].length);    // 2
10     }
11 }

Arrays 类

  1. 数组的工具类 java.util.Arrays

  2. Arrays 类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用

  3. 具有以下常用功能:

  • 给数组赋值:通过 fill 方法

  • 对数组排序:通过 sort 方法

  • 比较数组:通过 equals 方法比较数组中元素值是否相等

  • 查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作

  1. 可借助 JDK 帮助文档进行使用相关内容

  2.  1 public static void main(String[] args) {    
     2     int[] a = {1,2,3,4,9898,36523,498561,4512};    
     3     System.out.println(a);    
     4     //打印数组元素 Arrays.toString    
     5     Arrays.sort(a); //数组进行排序-升序    
     6     System.out.println(Arrays.toString(a)); 
     7     
     8     Arrays.fill(a,2,4,0);  //数组填充  此处2和4表示从第二位到第四位填充为0
     9     System.out.println(Arrays.toString(a));    
    10 }

     


冒泡排序

冒泡排序代码:两层循环,外层冒泡轮数,里层依次比较。时间复杂度为O(n2)

 1 public static void main(String[] args) {
 2         int[] a = {5,158,45,6,89,68,12,39,56,45,53};
 3         int[] sort = sort(a);  //调用完自己写的排序方法以后,返回一个排序后的数组
 4         System.out.println(Arrays.toString(sort));
 5     }
 6 
 7     //冒泡排序
 8     //1. 比较数组中,两个相邻的元素,如果第一个数比第二个数大,就交换二者位置
 9     public static int[] sort(int[] array){
10         //临时变量
11         int temp = 0;
12         //外层循环,判断要走多少次;
13         for (int i = 0; i < array.length-1; i++) {
14             boolean flag = false;  //通过flag标识位减少无意义的比较
15             //内层循环,比较判断两个数,若第一个数比第二个数大,则交换位置
16             for (int j = 0; j < array.length-1-i; j++) {
17                 if (array[j+1] < array[j]){
18                     temp  = array[j];
19                     array[j] = array[j+1];
20                     array[j+1] = temp;
21                     flag = true;
22                 }
23             }
24             if (flag == false){
25                 break;
26             }
27         }
28         return array;
29     }
30 }

 

稀疏数组

  1. 当一个数组中大部分元素为0时,或者为同一值的数组时,可以使用稀疏数组来保存该数组。

  2. 稀疏数组的处理方式是:

  • 记录数组一共有几行几列,有多少个不同值

  • 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模

 1 public class ArrayDemo08 {    
 2     public static void main(String[] args) {        
 3         //1. 创建一个二维数组  11*11   0:没有棋子  1:黑棋  2:白棋        
 4         int[][] array1  = new int[11][11];        
 5         array1[1][2] = 1;       array1[2][3] = 2;        
 6         //输出原始数组        
 7         System.out.println("输出原始的数组");        
 8         for (int[] ints : array1) {      //快捷方式: array1.for + 回车            
 9             for (int anInt : ints) {      //快捷方式: ints.for + 回车                
10                 System.out.print(anInt+"\t");            
11             }            
12             System.out.println();        
13         }        
14         System.out.println("===================================");        
15         //转换为稀疏数组保存        
16         //获取有效值的个数        
17         int sum = 0;        
18         for (int i = 0; i < 11; i++) {            
19             for (int j = 0; j < 11; j++) {                
20                 if (array1[i][j] != 0){ sum++; }             
21             }        
22         }        
23         System.out.println("有效值的个数为:"+sum);        
24         //2. 创建一个稀疏数组的数组        
25         int[][] array2 = new int[sum+1][3];        
26         array2[0][0] = 11;   array2[0][1] = 11;    array2[0][2] = sum;        
27         //遍历二维数组,将非零的值,存放稀疏数组中        
28         int count = 0;        
29         for (int i = 0; i < array1.length; i++) {            
30             for (int j = 0; j < array1[i].length; j++) {                
31                 if (array1[i][j] != 0){                    
32                     count++;                    
33                     array2[count][0] = i;                    
34                     array2[count][1] = j;                    
35                     array2[count][2] = array1[i][j];                
36                 }            
37             }        
38         }        
39         //输出稀疏数组        
40         System.out.println("稀疏数组:");        
41         for (int i = 0; i < array2.length; i++) {            
42             System.out.println(array2[i][0]+"\t"                                
43                                +array2[i][1]+"\t"                                
44                                +array2[i][2]+"\t");        
45         }        
46         System.out.println("===================================");        
47         System.out.println("还原:");        
48         //1. 读取稀疏数组的值        
49         int[][] array3 = new int[array2[0][0]][array2[0][1]];        
50         //2.给其中的元素还原它的值        
51         for (int i = 1; i < array2.length; i++) {            
52             array3[array2[i][0]][array2[i][1]] = array2[i][2];        
53         }        
54         //3. 打印        
55         System.out.println("输出还原的数组");        
56         for (int[] ints : array3) {      //快捷方式: array1.for + 回车     
57             for (int anInt : ints) {      //快捷方式: ints.for + 回车  
58                 System.out.print(anInt+"\t");            
59             }            
60             System.out.println();        
61         }    
62     }
63 }

 


正式篇

面向对象编程

  1. 本质:以类的方式组织代码,以对象的组织(封装)数据。

  2. 三大特性:封装、继承、多态。

回顾方法及加深

  1. 方法的定义:

    • 修饰符、返回值类型

    • break:跳出Switch,结束整个循环

    • return:结束方法,返回一个结果

    • 方法名:注意规范,见名知意

    • 参数列表:(参数类型,参数名)...定义可变常参数

    • 异常抛出: 后面讲解

  2. 方法的调用:递归

    • 静态方法

    • 非静态方法

    • 形参和实参

    • 值传递和引用传递的区别:

     

    this 关键字

     

     


创建与初始化对象

  1. 使用 new 关键字创建对象

  2. 使用 new 关键字创建的时候,除了分配内存空间之外,还会给 创建好的对象 进行默认的初始化以及对类中构造器的调用

  3. 一个类中就只有两部分:属性 和 方法

//类是抽象的,需要实例化
//类实例化后会返回一个自己的对象
//student对象就是一个Student类的具体实例

构造方法(构造器)

  1. 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。

  2. 并且构造器有以下两个特点

  • 必须和类的名字相同

  • 必须没有返回类型/值,也不能写 void

  1. 作用:

  • 使用 new 关键字,本质是在调用构造

  • 构造器一般用来初始化值

  1. 快捷键: alt + insert 生成构造器(构造方法)

    生成有参构造方法:alt + insert ---> constructor ---> 选择需要生成的 ---> OK

    生成无参构造方法:alt + insert ---> constructor ---> 选择需要生成的 ---> select none


创建对象内存分析

参见 狂神视频 面向对象P65,即视频 面向对象06

 

简单小结类与对象

  1. 类与对象: 类是一个模板:抽象,对象是一个具体的实例

  2. 方法:定义、调用

  3. 对象的引用:

  • 引用类型:基本类型(8种),对象是通过引用来操作的:栈--->堆

  1. 属性:字段(Field/成员变量)

    默认初始化:数字: 0 0.0 char:u0000

    boolean:false 引用:null

    属性的定义: 修饰符 属性类型 属性名 = 属性值

  2. 对象的创建和使用

  • 必须使用 new 关键字创造对象,创造对象还需要构造器 Person xiaoming = new Person();

  • 对象的属性 xiaoming.name

  • 对象的方法 xiaoming.sleep()

  1. 类:一个类中就只有两部分:属性 和 方法

    静态的属性 即 属性

    动态的行为 即 方法


封装

  1. 该露的露,该藏的藏

    我们程序设计要追求 “高内聚,低耦合” 。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。

  2. 封装(数据的隐藏)

    通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。

  3. 属性私有,get / set

  4. 封装的意义:提高程序的安全性,保护数据; 隐藏代码的实现细节; 统一接口; 系统的可维护性增加了。

  5.  

  6. 有时还需考虑数据的合理性,如下图。图中设置年龄不太符合实际,便在右侧Student类中的setAge里进行相应限制条件的设置:

 


继承

  1. 继承的本质是对某一批类的抽象,子类继承了父类,就会拥有父类的全部方法。

  2. extends 意为 “扩展”。子类是父类的扩展。

  3. Java中,类只有单继承,没有多继承!

  4. 继承是类与类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。

  5. 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。

  6. 私有的东西无法被继承

Object 类

  1. Java中,所有的类都默认直接或间接继承 Object 类。

 

super 关键字

  1. super 调用父类的构造器,必须要在子类构造器的第一行。

  2. 注意点:

    • super 调用父类的构造方法,必须在构造方法的第一行;

    • super 必须只能出现在子类的方法或者构造方法中;

    • super 和 this 不能同时调用构造方法。

  3. super 与 this 的区别

    • 代表的对象不同:

      this :代表 本身调用者这个对象

      super : 代表 父类对象的应用

    • 前提 :

      this:没有继承也可以使用

      super:只能在继承条件才可以使用

    • 构造方法:

      this( ):调用本类的构造

      super( ):调用父类的构造

方法重写

  1. 重写都是方法的重写,和属性无关。

  2. 重写只跟非静态方法(成员方法)有关,而与静态方法无关;

  3. 静态方法和非静态方法是不一样的:

    在静态方法中,方法的调用只和左边声明的对象类型有关,而与右边无关,是哪个类型,就调用对应的方法。

 

  1. 注意:重写需要有继承关系,子类重写父类的方法

    • 方法名必须相同

    • 参数列表必须相同

    • 修饰符:范围可以扩大,但不可以缩小: public > Protected > Default > private

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

  2. 重写,子类的方法和父类必须要一致,但方法体不同。

  3. 为什么需要重写:

    • 父类的功能,子类不一定需要,或者不一定满足。 Alt + Insert : @Override

 


多态

  1. 多态,即同一种方法可以根据发送对象的不同而采用多种不同的行为方式。

  2. 多态注意事项:

    • 多态是方法的多态,属性没有多态

    • 父类和子类,有联系 类型转换异常--->ClassCastException

    • 存在的条件: ①有继承关系;②(子类重写父类方法)方法需要重写;

      ③父类引用指向子类对象---> Father f1 = new Son( );

  3. 不能重写的方法:

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

    • final 是常量;

    • private 方法,私有方法。

  4. Application.java

 1 package oop;
 2 import oop.demo06.Person;
 3 import oop.demo06.Student;
 4 
 5 public class Application {    
 6     public static void main(String[] args) {        
 7         //一个对象的实际类型是确定的        // 可以指向的引用类型就不确定了        
 8         //Student 能调用的方法都是自己的,或者继承父类的        
 9         Student s1 = new Student();        
10         //Person 是父类,可以指向子类,但是不能调用子类独有的方法        
11         Person s2 = new Student();  //父类的引用指向子类        
12         Object s3 = new Student();        
13        
14         //对象能执行哪些方法,主要看对象左边的类型,和右边关系不大        
15         s2.run();  //子类重写了父类的方法,执行子类的方法        
16         s1.run();        
17         // s2.eat();    // s2前面是Person,但Person类里没有eat(),所以此处不能使用该句    
18     }
19 }

 

Person.java

1 package oop.demo06;
2 public class Person {    
3     public void  run(){        
4         System.out.println("run");    
5     }
6 }

 

Student.java

 1 package oop.demo06;
 2 public class Student extends Person{    
 3     @Override    
 4     public void run() {        
 5         System.out.println("son");    
 6     }    
 7     public void eat(){        
 8         System.out.println("eat");    
 9     }
10 }

instanceof

  1. instanceof 是 Java 的保留关键字。

  2. 它的作用是,测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。

  3. System.out.println( X instanceof Y);

    能不能编译通过,取决于 X 与 Y 之间是否存在父子关系。

类型转换

1.

public static void main(String[] args) {    
    //类型之间的转化:  父   子    
    
    //高      --->      低    
    Person obj = new Student();    
    //student 将这个对象转换为Student类型,    
    // 我们就可以使用Student类型的方法了    
    ((Student)obj).go();
}
  1. 父类引用指向子类的对象

  2. 子转父,不可用子类特有方法,可获得子类重写父类的方法,可获得父类独有方法。

 

以下强制转换/自动转换不知道对否,待验证。

  1. 把子类转换为父类,由低到高,向上转型,自动转换

  2. 把父类转换为子类,向下转型:需要强制转换。 会丢失父类被子类所重写掉的方法。

    父类转子类会丢失子类特有的一些方法

  3. 以上3、4点可以类比基本数据类型的转换:

  • double 转 int ,丢失小数;int 转 double ,强制转换

 


static 关键字详解

  1. 静态变量输出时,可以直接用 类名.变量名 来输出。

  2. 加了 static 可以不创建对象,而使用类名.属性名或者方法名 直接调用。只是在本类里可以省去类名。

  3. 静态变量对于类,所有对象(实例)所共享,当直接使用类去调用得到说明这个变量是静态的。

  4. 类的加载顺序:静态代码块 > 匿名代码块 > 构造方法

     1 public class Person {    
     2     // 输出顺序:2   赋初值~    
     3     {        //代码块(匿名代码块)        
     4         System.out.println("匿名代码块");    
     5     }    
     6     // 输出顺序:1   , static 只执行一次~    
     7     static{        //静态代码块        
     8         System.out.println("静态代码块");    
     9     }    
    10     // 输出顺序:3    
    11     public Person() {        
    12         System.out.println("构造方法");    
    13     }    
    14     public static void main(String[] args) {        
    15         Person person1 = new Person();        
    16         System.out.println("=============================");        
    17         Person person2 = new Person();    
    18     }
    19 }

     


抽象类

  1. abstract 修饰符可以用来修饰方法,也可以修饰类。

  2. 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。

  3. 抽象类,不能使用 new 关键字类创建对象,它是用来让子类继承的。

  4. 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类继承的。

  5. 子类继承抽象类,就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

  6. 继承了抽象类的所有方法(包括抽象方法)的子类都必须要实现它的方法,除非子类也是抽象类。

  7. Java中,类是单继承的,接口可以多继承。

  8. 抽象类特点:

    • 不能new这个抽象类,只能靠子类去实现它:约束!

    • 抽象类中可以写普通的方法

    • 抽象方法必须在抽象类中

  9. 抽象类存在构造器吗?

  • 抽象类可以有构造方法,只是不能直接创建抽象类的实例对象而已。

    在继承了抽象类的子类中通过super()或super(参数列表)调用抽象类中的构造方法。

 


接口

  1. 声明接口的关键词是 interface;

  2. 接口的作用:

    • 约束

    • 定义一些方法,让不同的人实现

    • 接口中,所有定义的方法,其实都是抽象的 public abstract

    • public static final ~~ 属性其实都默认为常量,如 public static final int age;

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

    • implements 可以实现多个接口;

    • 必须要重写接口中的方法

 


内部类

  1. 内部类就是在一个类的内部再定义一个类。比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。

  2. 内部类可以直接访问外部类方法和属性,不需要创建外部类的对象

  3. 一个Java类中可以有多个class类,但是只能有一个 public class 类

  4. 类型:成员内部类、静态内部类、局部内部类、匿名内部类

     


异常机制

  • 检查性异常:最具代表性的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。

  • 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略

  1. Java把异常当做对象来处理,并定义一个基类 java.lang.Throwable 作为所有异常的超类。

在 Java API 中已经定义了许多异常类,这些异常类分为两大类,错误 ERROR 和 异常 Exception

 

Exception:

 

ERROR:

  1. 错误 ERROR :错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译时也检查不到的。

   2. 

 

 


异常处理机制

  1. 异常处理五个关键字:try、catch、finally、throw、throws

  2. 快捷键 : Ctrl + ALT + T ---> 选择代码块进行包裹代码(如:if/else , try/catch......)

 

自定义异常

  1.  

     

 

实际应用中的经验总结

 


 

 

 

 

 

 

posted @ 2022-03-13 17:59  Arthur_1668  阅读(83)  评论(0编辑  收藏  举报