Java 笔记

Java 入门

1、C & C++

  • 1972年C诞生
    • 贴近硬件,运行极快,效率极高。
    • 操作系统,编译器,数据库,网络系统等
    • 指针和内存管理
  • 1982年C++诞生
    • 面向对象
    • 兼容C
    • 图形领域,游戏等
  • 何为编程
    • 人与计算机交流的过程
    • 让计算机解决某个问题使用某种程序设计语言编写程序代码,最后返回结果的过程。

2、Java 特性和优势

  • 简单性 Java语言的语法与C语言和C++语言很接近
  • 面向对象 封装,继承,多态
  • 可移植性 使用字节码.clss文件
  • 高性能
  • 分布式
  • 动态性
  • 多线程 多线程机制使应用程序在同一时间并行执行多项任
  • 安全性
  • 健壮性 Java语言的强类型机制、异常处理、垃圾的自动收集等

注意:Java和C++的区别:

​ Java和C++都是面向对象的编程语言,都支持封装、继承、多态

​ Java不提供指针直接访问内存,程序内存更加安全

​ Java的类是单继承,C++的类是多重继承,但Java接口可以多重继承

​ Java有自动内存管理机制,不需要手动释放无用内存

3、Java 三大版本

  • JavaSE: 标准版(桌面程序,控制台开发......)
  • JavaME: 嵌入式开发 (手机,小家电....)
  • JavaEE: E企业级开发 (Web端,服务器开发....)

4、JDK JRE JVM

4.1、卸载jdk

  1. 删除java安装目录
  2. 删除环境设置JAVA_HOME、Path
  3. java -version 查看版本

4.2、安装jdk

注意:环境变量Path 下:

  • 配置 %JAVA_HOME%\bin
  • 配置 %JAVA_HOME%\ jre \bin

4.3、Jdk与Jre与Jvm的区别:

  • Jdk包含一些Jre之外的一些东西,就是这些东西帮助我们编译java代码,还包括监控JVM的一些工具。
  • JDK是开发人员使用的,其中包含Java开发工具 编译工具(javac.exe),打包工具(jar.exe) 也包含jre。
  • jre:大部分都是C、C++语言编写的,是编译Java代码的基础类库。
  • jre包含Java虚拟机和Java程序的核心类库等,核心类库:Java.lang包

4.4、什么是跨平台性?实现原理?

  • 跨平台性:指Java语言编写的程序,经过一次编译,可以在多个系统平台上运行
  • 原理:Java程序是通过Java虚拟机在系统平台上运行的,如果系统安装相应的Java虚拟机,则Java程序在该系统上运行。

5、第一个程序

Hello Word

  1. 随便新建一个文件夹,存放代码
  2. 新建一个java文件
    • 文件后缀名为.java
    • Hello.java
  3. 编写代码
/*语法*/
public class Hello{
    public static void main (String[] args){
        System.out.print("Hello,Word!");
    }
}
  1. 编译 javac java文件,会生成一个class文件
javac Hello.java
  1. 运行class文件
java Hello

可能会遇到的情况:

  • 每个单词的大小写不能出现问题,Java是大小写敏感的
  • 文件名和类名必须保证一致,并且首字母大写
  • 符号必须使用英文
  • java文件和class文件必须在同一个文件夹下

6、快捷键

优化

psvm  /*main方法*/
sout 
ctrl+D 复制当前行到下一行
alt+enter 导包
100.for + enter 自动生成循环体
alt+ insert 构造器
ctrl+h
Ctrl+Alt+T  处理异常

7、英文

struct  结构体
operator [ˈɑpəˌreɪtər] 关键字
method  方法

8、内存分析

Java 内存

  • 堆:

    • 存放new的对象的数组
    • 可以所有的线程共享,不会存放别的对象引用
  • 栈:

    • 存放基本变量类型(会包含这个基本类型的具体数值)
    • 引用对象变量(会存放这个引用在堆里面的具体地址)
  • 方法区:

    • 可以被所有的线程共享
    • 包含了所有的class和static变量

Java 基础

1、注释

// 单行注释 
/*
  多行注释
*/
/** JavaDos:文档注释*/

2、标识符

  • 关键字

  • Java 所有的组成部分都需要名字。类名、变量名及方法名都被称为标识符。

/*语法*/
// Hello 类名
public class Hello{
    // main 方法名
    public static void main (String[] args){
        // 变量名
        String teacher = "秦疆";
        
        System.out.print("Hello,Word!");
    }
}
  • 标识符注意点:

3、数据类型

3.1、强类型语言 java c c++

  • 要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用
  • 安全性高,速度慢

3.2、Java 的数据类型分为两大类

  • 基本类型
    • 数值类型
      • 整数类型: Byte 1字节、short 2字节、int 4字节、long 8字节:后加"L"区分
        • 拓展:进制 二进制0b 十进制 八进制0 十六进制0x 0~9 A~F
        • byte 最大 127
      • 浮点数类型:float 4字节后加"F"区分、 double 8字节
        • 拓展:银行业务怎么表示? 钱
          • float 有限 离散 舍入误差 大约
          • 使用 BigDecimal 数学工具类
      • 字符串类型:char 1字符 ,2字节, 一个汉字两字节
        • 拓展:Java语言采用Unicode编码标准 编码 Unicode 2字节
        • 转义字符:
          • \t 制表符
          • \n 换行
    • Boolean类型
      • 1字节,只有true和false [fɔls]
      • 拓展:boolean fiag = true;
        • if(flag==true){}
        • if(flag){}
  • 引用类型
    • 接口
    • 数组

3.3、类型转换

低---------------------------------------------->高
     byte,short,char->int->long->float->double
  • 运算中,不同类型的数据先转换同一类型,然后进行运算

输出类型比较高低

//强制转换 高---->低
int i = 128;
short b = (short)i;
System.out.println(b);
//自动转换  低------>高
int i = 0;
double d = i;
System.out.println(d);

注意:

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

System.out.println((int)23.7); //23
System.out.println((int)-45.89f); //-45

4、变量

4.1、变量

  • 变量是什么:就是可以变化的量!

  • Java是一种强类型语言,每个变量都必须声明其类型

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

    type  varName [=value] [{,varName[=value]}];
    //数据类型  变量名  =值 ; 可以用逗号隔开来声明多个同类型变量
    
  • 注意事项:

    • 每个变量都有类型,类型可以是基本类型,也可以是引用类型
    • 变量名必须是合法的标识符
    • 变量声明是一条完整的语句,因此每一个声明都比西以分号结束

4.2、变量作用域

  • 类变量
  • 实例变量 方法外部,类内部定义的变量
  • 局部变量 类的方法中的变量
public class 类名{
    //static 修饰符
    static int allClicks=0;  //类变量
    
    //实例变量:从属于对象 默认值 0
    // 布尔值:默认值false
    //除了基本类型,其余默认值都是null
    String str="hello word"; 
    
    public void method(){  //方法
        int i=0;//局部变量:必须声明和初始化
    }
}
  • 常量
final 常量名=值;
final double PI=3.14;

4.3、变量的命名规范

  • 所有变量、方法、类名:见名知意
  • 类成员变量:首字母小写和驼峰原则:monthSalary
  • 局部变量:首字母小写和驼峰原则
  • 常量:大写字母和下划线:MAX_VALUE
  • 类名:首字母大写和驼峰原则:Man,GoodMan
  • 方法名:首字母小写和驼峰原则:run(),runRun()

4.4、成员变量与局部变量的区别有哪些

变量:在程序执行的过程中,在某个范围内其值可以发生改变的量。从本质上讲,变量其实是内存
中的一小块区域
成员变量:方法外部,类内部定义的变量
局部变量:类的方法中的变量。

成员变量和局部变量的区别

作用域
成员变量:针对整个类有效。
局部变量:只在某个范围内有效。(一般指的就是方法,语句体内)

存储位置
成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中。
局部变量:在方法被调用,或者语句被执行的时候存在,存储在栈内存中。当方法调用完,或者语
句结束后,就自动释放。

生命周期
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:当方法调用完,或者语句结束后,就自动释放。

初始值
成员变量:有默认初始值。
局部变量:没有默认初始值,使用前必须赋值。

5、运算符

注意:

运算类型 结果类型 描述
long long
double double
其他 int 不绝对,大部分

%:取余

++ -- :自增 自减

  • a++ a=a+1; 先赋值,再自增
  • ++a 先自增,再赋值

幂运算

Math 工具类

double pow = Math.pow(3,2);
System.out.println(pow); // 得9

&&、||、!与 &、|、^、~关系

逻辑运算符 关系式 描述
&& 逻辑与 ab&&bc 同true,得true 短路运算
|| 逻辑或 ab||bc 一个true,得true
! !(a==b) 取反
位运算符 关系式 描述
& 按位与 A= 0011 1100 B = 0000 1101 得 A&B=0000 1100 A&B 都为1,得1
A|B= 0011 1101 A|B 都为0,得0
取反 ~B= 1111 0010 ~B 非A即B
相同为0,不同为1 A^B= 0011 0001 A^B 异或运算

短路运算:&&左边表达式的值是false,则&&右边表达式不进行运算

**<<左移,>>右移 **

  • << *2

    • 用最有效率的方法计算 2 乘以 8

    • 2 << 3(左移 3 位相当于乘以 2 的 3 次方,右移 3 位相当于除以 2 的 3 次方)。

  • >> /2

字符串连接符 +

//String  字符串在前拼接
int a =10;
int b =20;
System.out.println(""+a+b);
1020
System.out.println(a+b+"");
30

? : 三元运算符

//x ? y : z
//如果x==true,则结果为y

== 和 equals 的区别是什么
== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。(基本数
据类型 == 比较的是值,引用数据类型 == 比较的是内存地址)
equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:
情况1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过
“==”比较这两个对象。
情况2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来两个对象的内容相等;
若它们的内容相等,则返回 true (即,认为这两个对象相等)。

举个例子:
public class test1 {
	public static void main(String[] args) {
		String a = new String("ab"); // a 为一个引用
		String b = new String("ab"); // b为另一个引用,对象的内容一样
		String aa = "ab"; // 放在常量池中
		String bb = "ab"; // 从常量池中查找
		if (aa == bb) // true
			System.out.println("aa==bb");
		if (a == b) // false,非同一对象
			System.out.println("a==b");
		if (a.equals(b)) // true
			System.out.println("aEQb");
		if (42 == 42.0) { // true
			System.out.println("true");
		}
	}
}

说明:

String中的equals方法是被重写过的,因为object的equals方法是比较的对象的内存地址,
而String的equals方法比较的是对象的值。
当创建String类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相
同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个String对象。

6、JavaDoc

Java流程控制

1、Scanner 对象

定义:Scanner 类获取用户的输入

//基本语法
//创建Scanner对象
Scanner s = new Scanner(System.in);  //System.in 输入

通过Scanner类的 next() 与 nextLine() 方法获取输入的字符串

通过hasNext() 与 hasNextLine() 判断是否还有输入的数据

public class Scannerdemo{
    public ststic void main(String[] args){
        //创建一个扫描对象,用于接收键盘数据
        
         Scanner scanner = new Scanner(System.in);
        
        System.out.println("使用next方式接收:");
        
        //判断用户有没有输入字符串
        if(scanner.hasNext()){
           Scanner str= scanner.next();
           System.out.println("输出的内容为:"+str);
        }
        //凡是属于IO流的类如果不关闭会一直占用资源,要养好习惯用完就关闭掉
        scanner.close();
    }
}

next() 与 nextLine()

  • next():

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

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

2、三大结构

1、顺序结构

  • Java的基本结构就是顺序结构
  • 顺序结构是最简单的算法结构
  • 任何一个算法都离不开的一种基本算法结构

2、选择结构

2.1、if单选择结构

public class IfDemo1{
    public static viod main(String[] args){
        Scanner s = new Scanner(System.in);
        System.out.println("输入内容:");
        String str = s.nextLine();
        if(str.equals("Hello")){
           System.out.println(str);
        }
        System.out.println("End");
        s.close();
    }
}

2.2、if双选择结构

public class IfDemo2{
    public static viod main(String[] args){
        Scanner s = new Scanner(System.in);
        System.out.println("输入成绩:");
        int str = s.nextInt();
        if(str>60){
           System.out.println("及格");
        }else{
           System.out.println("不及格");
        }
        s.close();
    }
}

2.3、if多选择结构

public class IfDemo3{
    public static viod main(String[] args){
        Scanner s = new Scanner(System.in);
       /*
       if 语句至多有一个else语句,else语句在所有的else if语句之后
       if 语句可以有若干个else if 语句,它们必须在else 语句之前
       一旦其中一个else if 语句检测为true ,其它的elseif 以及else 语句都将跳过执行。
       */
        System.out.println("输入成绩:");
        int str = s.nextInt();
        if(str==100){
           System.out.println("满分");
        }else if(str<100&&str>=90){
           System.out.println("A");
        }else if(str<90&&str>=80){
           System.out.println("B");
        }else if(str<80&&str>=70){
           System.out.println("C");
        }else if(str<70&&str>=60){
           System.out.println("D");
        }else{
           System.out.println("不及格");
        }
        s.close();
    }
}

2.4、嵌套的if结构

if(布尔表达式1){
    //如果布尔表达式1的值为true执行代码
    if(布尔表达式2){
    //如果布尔表达式2的值为true执行代码
    }
}

2.5、Switch 多选择结构

/*
switch case 语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支
switch 语句中的变量类型可以是:
byte、short、int、char
switch 支持字符串String 类型
同时case标签必须为字符串常量或字面量
*/

char g = 'C';
Switch(g){ //布尔表达式g
    case 'A':
    System.out.println("优秀");
    break;
    case 'B':
    System.out.println("良");
    break;
    default:
    System.out.println("不及格");
}
//JDK7的新特性,表达式结果可以是字符串!
//字符串的本质还是数字
//反编译 java-----class(字节码文件)----反编译IDEA
String name = "狂神";
Switch(name){
    case "秦疆":
    System.out.println("秦疆");
    break;
    case "狂神":
    System.out.println("狂神");
    break;
    default:
    System.out.println("弄啥嘞");
}

3、循环结构

3.1、while 循环

/*
while 是最基本的循环
结构:while(布尔表达式){
循环内容
}
只要布尔表达式为true,循环就会一直执行下去 死循环
我们大多数情况是会让循环停止下来的
少部分情况需要循环一直执行,比如服务器的请求响应监听等
*/

int i=0;
while(i<100){
    i++;
    System.out.println(i);
}

//思考:1+2+3+...+100?
int i=0;
int sum=0;
while(i<=100){
    sum = sum+i;
    i++;
}
    System.out.println(sum);

3.2、do.....while 循环

/*
do....while 循环至少执行一次
while与do... while区别:
while 不满足条件,则不能进入循环
while 先判断后执行,do..while是先执行后判断
Do...while总是保证循环体会至少被执行一次
*/
int i=0;
int sum=0;
do{
    sum = sum+i;
    i++;
}while(i<=100);
    System.out.println(sum);

3.3、for 循环

/*
for 循环执行的次数在执行前就确定
for(初始化;布尔表达式;迭代更新){
//代码语句
}
*/
//死循环
for(;;){
    
}

//练习:计算0到100之间的奇数和偶数的和
int addSum =0;
int evenSum =0;
for(int i = 0;i<=100;i++){
    if(i%2!=0){
        addSum+=i;
    }else{
        evenSum+=i;
    }
   System.out.println("奇数和:"+addSum);
   System.out.println("偶数和:"+evenSum);
}
//用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个
for(int i=0;i<=1000;i++){
    if(i%5==0){
    System.out.print(i+"\t");
    }
    if(i%(5*3)){
     System.out.println();//换行
     System.out.print("\n");//换行
    }
    //println 输出完会换行
    //print 输出完不会换行
}
//打印九九乘法表
//第一步:打印第一列
for(int i=1;i<=9;i++){
   System.out.println(1+"*"+i+"="+(1*i));
}

//第二步,把固定的1再用一个循环包起来
for(int j=1;j<=9;j++){
    for(int i=1;i<=9;i++){
     System.out.println(j+"*"+i+"="+(j*i));
   }
}
//第三步,去掉重复项,i<=j
//第四步调整样式
for(int j=1;j<=9;j++){
    for(int i=1;i<=j;i++){
     System.out.print(j+"*"+i+"="+(j*i)+"\t");
   }
   System.out.println();//换行
}

3.4、增强for

/*
Java5 引入了一种主要用于数组或集合的增强型for循环
语法:
for(声明语句:表达式){
//代码句子
}
声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。
其作用域限定在循环语句块,其值与此时数组元素的值相等。
表达式:表达式是要访问的数组名,或者是返回值为数组的方法。
*/

int[] numbers={10,20,30,40,50}; 定义一个数组
//遍历数组的元素
for(int x:numbers){  //数组中元素依次输出
  System.out.println(x);
}

4、break 和 continue

break在任何循环语句的主体部分,均可用break控制循环的流程。
break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
**关于goto关键字**保留字
goto关键字很早就在程序设计语言中出现。尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用;Java没有goto。
然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子---带标签的break和continue.
“标签”是指后面跟一个冒号的标识符,例如: label:
对Java来说唯一用到标签的地方是在循环语句之前
而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另-个循环,
由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。

Java 方法

1、何谓方法?

Java是值传递

  • System.out.println(),是什么?
    • System ---类
    • out ---输出对象
    • println()----方法

Java 方法是语句的集合,它们在一起执行一个功能

  • 方法是解决一类问题的步骤的有序组合
  • 方法包含于类或对象中
  • 方法在程序中被创建,在其他地方被引用
  • 一个方法只完成1个功能
//main方法
public static void main(String[] args){
   //实际参数:实际调用传递给他的参数
    int sum = add(1,2);
    System.out.println(sum);
}
//public static 修饰符
//void 返回值类型(无返回值)

//加法方法
//形式参数,用来定义的作用
public static int add(int a,int b){
    return a+b;
}

方法包含一个方法头和一个方法体。下面是一个方法的所有部分:

修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
返回值类型︰方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void。
方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
形式参数:在方法被调用时用于接收外界输入的数据。
实参:调用方法时实际传给方法的数据。
方法体:方法体包含具体的语句,定义该方法的功能。

    
修饰符  返回值类型  方法名(参数类型 参数名){
    。。。
    方法体
    。。。
    return 返回值;
}

//比大小

public static int max(int num1,int num2){
    int result = 0;
    if(num1==num2){
       System.out.println("num1=num2");
       return 0 ;//终止方法
    }
    if(num1>num2){
        return result = num1;
    }else{
        return result = num2;
    }
    return result;
}

//调用方法:对象名.方法名(实参列表)
//Java支持两种调用方法的方式,根据方法是否返回值来选择
//当方法返回一个值的时候,方法调用通常被当作一个值
int larger = max(30,40);
//如果方法返回值是void,方法调用一定是一条语句
System.out.println("Hello Word");

值传递:指的是在方法调用时,传递的参数是按值的拷贝传递,传递的是值的拷贝,也就是说传递后就互不相关了。
引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。

2、方法重载

重载就是在一个类中,有相同的函数名称,但形参不同的函数。
方法的重载的规则:
方法名称必须相同。
参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。
方法的返回类型可以相同也可以不相同。
仅仅返回类型不同不足以成为方法的重载。
实现理论:
方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。

可变参数/不定项参数

  • jdk1.5开始,Java支持传递同类型的可变参数给一个方法。
  • 在方法声明中,在指定参数类型后加一个省略号(...)。
  • 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。
  • 任何普通的参数必须在它之前声明。
public static void main(String[] args){
    //new一个对象
     Demo04 demo04 = new Demo04();
     //对象名.方法名()
    demo04.test(1,2,3,4,5)//可以输入值,相同类型
}
public void test(int x,int...i){  //int...i 必须放到最后面
   System.out.println(i[0]);//第0个
}

3、递归

递归就是:A方法调用A方法!就是自己调用自己
递归结构包括两个部分:
递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
递归体:什么时候需要调用自身方法。
/*
阶层
1!1
2!2*1
3!3*2*1
*/
public static void main(String[] args){
   System.out.println(f(5));
}
public static int f(int n){
    if(n==1){
        return 1;
    }else{
        return n*f(n-1);
    }
}

Java 数组

1、什么是数组?

  • 数组是相同类型数据的有序集合
  • 数组描述的是相同类型的若干数据,按照一定的先后次序排列组合。
  • 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。

2、数组声明创建

  • 首先必须声明数组变量,才能在程序中使用数组。方法:
dataType[] arrayRefVar;//首选的方法
或
dataType arrayRefVar[];//效果相同
  • Java语言使用new操作符来创建数组,语法如下:
//数组类型    数组变量名                  数组大小
dataType[] arrayRefVar = new dataType[arraySize]
//这里面可以存放10个int类型的数字             
 int[] nums = new int[10];
//给数组元素赋值
nums[0] = 1;
nums[1] = 2;
//计算所有元数的和
int sum = 0;
//获取数组长度,arrays.length
for(int i=0; i<nums.length;i++){
    sum+=nums[i];
}
System.out.println(sum);
  • 数组元素是通过索引访问的,数组索引从0开始。
  • 获取数组长度:
arrays.length

3、三种初始化

  1. 静态初始化

    //创建+赋值
    int [] a = {1,2,3};
    Man[] mans = {new Man(1,1),new Man(2,2)}
    
  2. 动态初始化

    int [] a = new  int[2];
    
    a[0]=1;
    
    a[1]=2;
    
  3. 数组的默认初始化

4、数组的特点

  1. 其长度是确定的数组一旦被创建,它的大小就是不可以改变的。
  2. 其元素必须是相同类型,不允许出现混合类型。
  3. 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
  4. 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。
  5. 数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。

5、数组的使用

**for - Each **

//arrays.for快捷创建
//jdk 1.5 没有下标
for(int array:arrays){
System.out.println(array);
}

数组作方法入参

printArray(arrays);
//打印数组元素
public static viod printArray(int[] arrays){
    for(int i=0; i<arrays.length;i++){
        System.out.println(arrays[i]+"");
    }
}

数组作返回值

int[] reverse = reverse(arrays);
printArray(reverse);
//反转数组
public static int[] reverse(int[] arrays){
    int result = new int[arrays.length];
    //反转的操作
    for(int i =0;j=rssult.length;i<arrays.length;i++,j--){
        result[j]=arrays[i];
    }
    return result;
}

6、二维数组(了解)

int a[][] = new int[2][5];
//[4][2]
int[][] array= {{1,2},{2,3},{3,4},{4,5}};

7、Arrays 类

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

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

8、冒泡排序

冒泡排序无疑是最为出名的排序算法之一,总共有八大排序!

冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层一次比较

//冒泡排序
//1.比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置
//2.每一次比较,都会产生出一个最大,或者最小的数字
//3.下一轮则可以少一次排序
//4.依次循环,直到结束

9、稀疏数组(扩展)

数据结构

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

稀疏数组的处理方式是:
记录数组一共有几行几列,有多少个不同值
把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模

Java 面向对象

1、面向过程&面向对象

  • 面向过程思想
    步骤清晰简单,第一步做什么,第二步做什么.…...
    面对过程适合处理一些较为简单的问题

  • 面向对象思想
    物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
    面向对象适合处理复杂的问题,适合处理需要多人协作的问题!

    对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。

2、什么是面向对象

  • 面向对象编程(OOP)
  • 面向对象编程的本质就是:以类的方式组织代码,以对象的形式(封装)数据。
  • 抽象
  • 三大特性:
    • 封装
    • 继承
    • 多态
  • 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
  • 从代码运行角度考虑是先有类后有对象。类是对象的模板。

3、回顾方法及加深

  • 方法的定义
    • 修饰符
    • 返回类型
    • break和return的区别:return 方法结束
    • 方法名
    • 参数列表 (参数类型,参数名)
    • 异常抛出:throws IOException
  • 方法的调用
    • 静态方法 : 加static修饰,类名.方法名();调用
    • 非静态方法 :
      • 先实例化这个类new, new 类名().方法名();
      • 对象类型 对象名 = 对象值;new 类名();
      • 对象名.方法名();
    • 形参和实参:类型要对应
    • 值传递和引用传递
//值传递
public class Demo{
    public static void main(String[] args){
         int a=1;
        Demo.change();
        System.out.println(a);
        
    }
    //返回值为空
    public static void change(int a){
        int a =10;
    }
}
//引用传递:对象:本质还是值传递
public class Demo{
    public static void main(String[] args){
     Perosn perosn = new Perosn();
     System.out.println(perosn.name);// null
     Demo.change(perosn);
     System.out.println(perosn.name);//秦疆
    }
    public static void change(Perosn perosn){
        perosn.name="秦疆";
    }
    class perosn{
        String name;
    }
}

4、类与对象的关系

  • 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。
    • 动物、植物、手机、电脑
    • Person类、Pet类、Car类 这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为。
  • 对象是抽象概念的具体实例

5、创建与初始化对象

使用new关键字创建对象
使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。

并且构造器有以下俩个特点:
1.必须和类的名字相同
2.必须没有返回类型,也不能写void

构造器

public class Person{
    String name;//属性
    //一个类即使什么都不写,它也会存在一个方法
    //实例化初始值,使用new关键字,本质是在调用构造器方法
    //显示的定义构造器
    public Person(){};
    //有参构造:一旦定义有参构造,无参构造必须显示定义
    public Person(String name){
        this.name =name;
    }
    
}

启动类

public class Application{
    public static void main(String[] args){
        //new 实例化一个对象
       Person person = new Person();//调用无参构造
       Person person = new Person("kuangshen");//调用有参构造
       System.out.println(person.name);
    }
}

注意:一个项目只存在一个main方法,一个启动类

构造器:
    1.和类名相同
    2.没有返回值
作用:
    1.new本质调用构造方法
    2.初始化对象的值
注意点:定义有参构造后,如果想使用无参构造,显示的定义一个无参构造

Java 封装、继承、多态

1、封装

该露的露,该藏的藏
我们程序设计要追求“高内聚,低耦合”。

​ 高内聚就是类的内部数据操作细节自己完成,把一个对象的属性私有化,不允许外部干涉;

​ 低耦合:仅暴露少量的方法给外部使用。
封装(数据的隐藏)
​ 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
记住这句话就够了:属性私有,get/set

作用:

  1. 提高程序的安全性,保护数据
  2. 隐藏代码的实现细节
  3. 统一接口
  4. 系统可维护增加了

Java 修饰符:

  • public :对所有类可见,使用对象 类、接口、变量、方法
  • default:对同一包可见,使用对象 类、接口、变量、方法 ,不使用任何修饰符
  • private [ˈpraɪvət] : 对同一类可见,使用对象 变量、方法
  • protected [prəˈtektəd]:对同一包的类和所有子类可见,使用对象 变量、方法

2、继承

继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
extends的意思是“扩展”。子类是父类的扩展。
JAVA中类只有单继承,没有多继承!
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键extends来表示。
子类和父类之间,从意义上讲应该具有"is a"的关系.
继承:
让某个类型的对象获得另一个类型的对象的属性的方法。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
关于继承如下 3 点请记住:
     子类拥有父类非 private 的属性和方法。
     子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
     子类可以用自己的方式实现父类的方法。

3、Super、this 关键字

3.1、this关键字的用法

this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针
this的用法在java中大体可以分为3种:
1.普通的直接引用,this相当于是指向当前对象本身。
2.形参与成员名字重名,用this来区分:

public Person(String name, int age) {
   this.name = name;
   this.age = age;
}

3.引用本类的构造函数

class Person{
	private String name;
	private int age;
	public Person() {
	}
	public Person(String name) {
		this.name = name;
	}
	public Person(String name, int age) {
		this(name);
		this.age = age;
	}
}

3.2、super关键字的用法

super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。
super也有三种用法:
1.普通的直接引用
与this类似,super相当于是指向当前对象的父类的引用,这样就可以用super.xxx来引用父类的成员。
2.子类中的成员变量或方法与父类中的成员变量或方法同名时,用super进行区分

class Person{
	protected String name;
	public Person(String name) {
		this.name = name;
	}
}
class Student extends Person{
	private String name;
	public Student(String name, String name1) {
		super(name);
		this.name = name1;
	}
	public void getInfo(){
		System.out.println(this.name); //Child
		System.out.println(super.name); //Father
	}
}
public class Test {
	public static void main(String[] args) {
		Student s1 = new Student("Father","Child");
		s1.getInfo();
	}
}



3.引用父类构造函数
super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。
this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。

3.3、this与super的区别

super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)
this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
super()和this()类似,区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。
super()和this()均需放在构造方法内第一行。
尽管可以用this调用一个构造器,但却不能调用两个。
this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。

this:它代表当前对象名,没有继承也可以使用
super:它引用当前对象的直接父类中的成员,只能在继承条件使用
this():是从本类中调用本类的其它构造方法、 super():是从子类内调用父类的构造方法
this()和super()都放在构造方法的第一行,均不可在static中使用
this和super不能同时出现在一个构造函数里
this的本质是指向本对象的指针,super是Java的一个关键字

4、重写、重载

  1. 重写Override

  2. 重载Overload

  3. 关系:

    重载与重写都是实现多态的方式,重载是实现的是编译时的多态性,重写是实现的是运行时的多态性
    重载:发生在同一类中,方法名相同,参数列表不同,与方法返回值和访问修饰符无关。
    重写:发生在父子类中,方法名、参数列表必须相同。
         抛出异常:范围可以被缩小,但不能扩大。Exception大
         访问修饰符:范围可以扩大但不能缩小。
         如果父类方法 ,访问修饰符为private,子类中就不是重写
    

5、多态

多态:对于同一个行为,不同的子类对象具有不同的表现形式。
多态存在的3个条件:
1)继承:继承关系
2)重写:方法需要重写
3)子类的引用赋给父类对象;父类的引用指向子类对象
多态是方法的多态,属性没有多态

6、static 关键字

6.1、static 存在的主要意义

  • static [ˈstætɪk] 的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法!
  • 用来形成静态代码块以优化程序性能。
  • static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
  • 很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。

6.2、static的独特之处

1、被static修饰的变量或者方法是独立于该类的任何对象,也就是说,这些变量和方法不属于任何一个实例对象,而是被类的实例对象所共享。

2、在该类被第一次加载的时候,就会去加载被static修饰的部分,而且只在类第一次使用时加载并进行初始化,注意这是第一次用就要初始化,后面根据需要是可以再次赋值的。
3、static变量值在类加载的时候分配空间,以后创建类对象的时候不会重新分配。赋值的话,是可以任意赋值的!
4、被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。

6.3、static应用场景

因为static是被类的实例对象所共享,因此如果某个成员变量是被所有对象所共享的,那么这个成员变量就应该定义为静态变量。
因此比较常见的static应用场景有:
1、修饰成员变量
2、修饰成员方法
3、静态代码块
4、修饰类【只能修饰内部类也就是静态内部类】
5、静态导包

静态变量和实例变量区别
     静态变量: 静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。
     实例变量: 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。

静态变量与普通变量区别
    static变量也称作静态变量,
    静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
    还有一点就是static成员变量的初始化顺序按照定义的顺序进行初始化。
静态方法和实例方法有何不同?
    静态方法和实例方法的区别主要体现在两个方面:
      在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。
      静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制。
在一个静态方法内调用一个非静态成员为什么是非法的?
    由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。

7、接口

inference关键字

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

7.1、抽象类和接口的对比

抽象类是用来捕捉子类的通用特性的。接口是抽象方法的集合。
从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。
相同点

  • 接口和抽象类都不能实例化
  • 都位于继承的顶端,用于被其他实现或继承
  • 都包含抽象方法,其子类都必须覆写这些抽象方法

不同点

参数 抽象类 接口
声明 抽象类使用abstract关键字声明 接口使用interface关键字声明
实现 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现 子类使用implements关键字来实现接口。它需要提供接口中所有声明的方法的实现
构造器 抽象类可以有构造器 接口不能有构造器
访问修饰符 抽象类中的方法可以是任意访问修饰符 接口方法默认修饰符是public,并且不允许定义为 private 或者protected
多继承 个类最多只能继承一个抽象类 一个类可以实现多个接口
字段声明 抽象类的字段声明可以是任意的 接口的字段默认都是 static 和 final的
备注:Java8中接口中引入默认方法和静态方法,以此来减少抽象类和接口之间的差异。

接口和抽象类各有优缺点,在接口和抽象类的选择上,必须遵守这样一个原则:
行为模型应该总是通过接口而不是抽象类定义,所以通常是优先选用接口,尽量少用抽象类。
选择抽象类的时候通常是如下情况:需要定义子类的行为,又要为子类提供通用的功能。

普通类和抽象类有哪些区别?
普通类不能包含抽象方法,抽象类可以包含抽象方法。
抽象类不能直接实例化,普通类可以直接实例化。

8、内部类

定义:内部类就是在一个类的内部在定义一个类。

比如:A类中定义一个B类,B类相对A类就是内部类,A类相对B类就是外部类

成员内部类

//外部类
public class Outer{
    private int id=10; //属性
    public void out(){
        System.out.println("这是外部类方法");
    }
    //内部类
    public class Inner{
       public void in(){
           System.out.println("这是内部类方法");
    }
    
        //获得外部类的私有属性
        public void getId{
            System.out.println(id);
        }
   }
}
//启动类
public class Application{
    public static void main(String[] args){
        //new一个外部类
      Outer outer =  new Outer();
        //通过这个外部类来实例化内部类
      Outer.Inner inner = outer.new Inner();
    }
}

静态内部类

局部内部类

//外部类
public class Outer{
   
    public void method(){
    //局部内部类
       public class Inner{
          public void in(){
             System.out.println("这是局部内部类方法");
         }
      }        
   }
}

匿名内部类

public class Test{
    public static void main(String[] args){
        //没有名字初始化类,不用将实例保存到变量中
        new Apple().eat();
    }
}
class Apple{
    public void eat(){
        System.out.println("1");
    }
}

Java 异常机制

1、什么是异常

Exception

要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。
错误ERROR:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

在Exception分支中有一个重要的子类RuntimeException(运行时异常)
ArraylndexOutOfBoundsException(数组下标越界)
NullPointerException(空指针异常)
ArithmeticException(算术异常)
MissingResourceException(丢失资源)
ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;
Error和Exception的区别: Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。

Error

Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止;
还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。

2、异常处理机制

捕获异常Ctrl+Alt+T

int a = 1;
int b = 0;
try{//try监控区域
   System.out.println(a/b);
}catch(ArithmeticExceptioncatch){// catch(想要捕获的异常类型)捕获异常
   System.out.println("程序出现异常,变量b不能为0");
}finally{//处理善后工作,可以不要,假设IO,资源,关闭1
   System.out.println("finally");
}

抛出异常

方法上抛出异常:throws

throw:主动抛出异常

posted @ 2023-01-25 16:24  雪断残阳  阅读(3)  评论(0)    收藏  举报