csdn都快放不下的 面试必备的java 基础以及 面对对象知识



文章目录

第一部分 语法

第一章 计算机基础

jiva技术架构

  • JavaSE Java Standard Edition Java标准版:桌面型应用程序
  • JavaEE Java Enterprise Edition Java企业版:服务器应用程序
  • JavaME Java Micro Edition Java微型版:嵌入式应用程序

java最大的特点——跨平台

跨平台的意思就是说,一个软件可以在多个平台上运行,而不用更改软件的内容。

是因为JVM的功劳:JVM(Java Virtual Machine)Java虚拟机。

Java源代码文件后缀名为xxx.java 所编译出来的二进制文件后缀名为xxx.class

JVM主要负责将java语言的字节码文件转换为本地操作系统指令的一个工具软件。 所以,最终是字节码文件在跨平台!

JDK的下载与安装

  1. 先登录注册Oracle
  2. 去Oralce官网下载JDK,最新JDK15,我们目前用JDK8 https://www.oracle.com
  3. 点击Products
  4. 点击SoftWare下的Java
  5. 右上角DownloadJava
  6. 找到JavaSE8 点击JDK Download
  7. 下拉 在下载列表中选择Windows X64
  8. 双击打开jdk安装程序
  9. 点击下一步
  10. JDK不需要更改目录 直接下一步
  11. JRE不需要更改目录 直接下一步
  12. 安装完成 点击关闭即可
  13. 验证jdk是否安装成功
  14. win+r 打开cmd 输入 java -version
java version "1.8.0_77" `

`Java(TM) SE Runtime Environment (build 1.8.0_77-b03) `

`Java HotSpot(TM) 64-Bit Server VM (build 25.77-b03, mixed mode)

配置path环境变量

  1. 复制jdk中bin目录的绝对地址 C:\Program Files\Java\jdk1.8.0_77\bin
  2. 右键此电脑 点击属性
  3. 点击高级系统设置
  4. 点击环境变量
  5. 系统变量中选择Path
  6. 右上角 新建 将地址复制进去即可
  7. 一路确定出去
  8. 重启cmd 再去尝试javavc java

VSCode修改方式

VSCode代码编辑器 https://code.visualstudio.com/

汉化:左下角管理 Extension 搜索Chinese 选择Chinese中文简体汉化包 点击绿色install 右下角提示 重启 重启即可

主题:管理 颜色主题 自选

编码:管理 设置 文本编辑器 文件 Encoding 选择gbk结尾

字体:管理 设置 文本编辑器 字体 font size

关联代码所在的文件夹:文件 打开文件夹 选择JavaDay01

运行java程序

步骤一:新建Java源代码文件并写入类

点击新建文件按钮,输入Java源代码文件名称和后缀名,例如 JavaDay01.java 在文件中写入如下代码:

public class  JavaDay01 {
}

注 : public class Sample01 中的 Sample01 是类名,而且在Java源代码中,可以存在多个类,但是 最多只能有一个public开头的类,并且该类的类名必须与文件名保持一致!!!
步骤二:编译该代码文件

打开控制窗口cmd,将目录切换到javaDay01目录下

C:\Users\HX>cd Desktop\\xuexi\\javademo

再输入 javac Sample01.java 对源代码文件进行编译

C:\Users\HX\Desktop\xuexi\javademo<javac JavaDay01.java

如果没有任何输出,则表明编译成功,并生成同名的字节码文件 Sample01.class

步骤三:运行该字节码文件

输入 java javaday01即可

C:\Users\HX\Desktop\xuexi\javademo<java JavaDay01

第二章 基本数据与运算

关键字

关键字是指被高级编程语言赋予特殊含义的一些单词,关键字一般都是由小写字母组成。好比是汉 语当中的一些专有名词:北京,天安门,兵马俑。不能乱用。

  • 用于定义数据类型的关键字:byte short int long float double char boolean void class interface
  • 用于定义数据类型值的关键字:true false null
  • 用于定义流程控制语句的关键字:if else switch case default while do for break(退出当前循环) continue(结束当前循环) return
  • 用于定义访问权限修饰符的关键字:public protected private
  • 用于定义继承关系的关键字:extends(继承) implements(实现接口)
  • 用于定义实例对象的关键字:new this super instanceof
  • 用于定义函数类型的关键字:static final abstract synchronized(同步线程)
  • 用于处理异常的关键字:try catch finally throw throws
  • 用于包的关键字:package import
  • 其他的一些修饰关键字:native assert volatile transient

标识符

标识符指的是我们在程序中对变量、函数、类、接口、常量所定义的名称,也就是说这些名称是我 们自定义的。

标识符必须满足以下组成规则:

  • 标识符可以由数字、字母、下划线 _ 、美元符 $ 组成
  • 标识符不能以数字开头,当然下划线和美元符其实是可以开头的,但不推荐
  • 标识符不能是关键字
  • 标识符也不能是Java内置类的名称
  • 标识符可以为任意长度,但必须是一个连续的词
  • 标识符严格区分大小写

注释

​ 注释是用于注解和说明程序的一些程序中的内置文本信息的,但这些内置文本不属于代码的范畴。 所以在对含有注释的源代码进行编译时,所生成的字节码中不含有注释。注释是给人看的!

​ 注释主要有三种:

  • 单行注释 //注释内容 直到换行为止
  • 多行注释 /* 注释内容 内部可以进行换行*/
  • 文档注释 /** 注释内容 内部可以进行换行 */ :文档注释可以被编译器识别,并生成相应 的程序说明书。对某一个类进行文档生成时,该类必须是public型

常量与进制

常量就是指在程序中直接出现的一些数据,也叫字面量

常量都有哪些:

  • 整数常量
  • 小数常量
  • 字符常量:由一个字母、数字、符号被单引号( ‘’ )标识的数据
  • 字符串常量:由若干个字母、数字、符号被双引号( “” )标识的数据
  • 布尔类型常量
  • null常量
public class Sample {
public static void main(String[] args) {
//整数常量
System.out.println(10); //十进制整数
System.out.println(0b1001); //二进制整数 打印出来是十进制
System.out.println(0123); //八进制整数
System.out.println(0xAF3); //十六进制整数
//小数常量
System.out.println(3.14);
System.out.println(5.234e3);
System.out.println(1.2e-3);
//字符常量
System.out.println('a');
//System.out.println('ab'); ERROR
System.out.println('9');
//System.out.println('12'); ERROR
System.out.println('我');
System.out.println(' ');
//System.out.println(''); ERROR
//System.out.println('''); ERROR
System.out.println('\''); //打印 '
System.out.println('\n'); //打印 换行
System.out.println('\t'); //打印 缩进
//字符串常量
System.out.println("abcd");
System.out.println("a");
System.out.println(""); //字符串空串 vs null真空
System.out.println("\"");
//布尔常量
System.out.println(true);
System.out.println(false);
}
}

原反补的转换

原码

转换 当x 大于0时 x=x

​ 当x大于0且小于1时 x=x

​ 例如 0.1111=0.1111

​ 当x为整数时 x=x

​ 例如 01111=01111

​ 当x 小于0时 x= 1-x=1+|x|

​ 当x为小数时 x=(2-2^(-n))+x

​ 例如 1.1111=1.0000

​ 当x为整数时 x=2n-x=2n+|x|

​ 例如 11111=11111

反码

转换 当x 大于0时 x=x

​ 当x大于0且小于1时 x=x

​ 例如 0.1111=0.1111

​ 当x为整数时 x=x

​ 例如 01111=01111

​ 当x 小于0时

​ 当x为小数时 x=(2-2^(-n))+x

​ 例如 1.1111 = 1.0000

​ 当x为整数时 x=(2^(n+1)-1)+x

​ 例如 11111= 10000

补码

转换 当x 大于0时 x=x

​ 当x大于0且小于1时 x=x

​ 例如 0.1111=0.1111

​ 当x为整数时 x=x

​ 例如 01111=01111

​ 当x 小于0时

​ 当x为小数时 x=2+x=2-|x|

​ 例如 1.0001=1.1111

​ 当x大于1时 x=2(n+1)+x=2(n+1)-|x|

​ 例如 11110=10010

移码

补码符号位相反即可

例题
真值原码反码补码
+700100011001000011001000110
-70110001101011100110111010
-0.8751.11101.00011.0010
0.8750.11100.11100.1110
+00.00000.00000.0000
-01.00001.11110.0000
-1.0000无法表示1.11111.0000

变量

指的是变化的量

  • 变量的本质就是在内存中程序所处的进程中的一个临时存储区域
  • 该区域的存储值有限制的
  • 该区域值的变化必须是同类型的或向下兼容的
  • 该区域有其自身的物理内存地址-指针
  • 该区域中 存储值的限制 和 数据的变化类型 由 数据类型 来决定
  • 该区域中 其空间的分配 和 空间的物理内存地址 由计算机底层来决定

回顾一下指针

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qQvr0jPE-1638149989083)(/QWGC70%5DWXPY%5BG@@XRPT2XOO.png)]

#include<stdio.h>
void main() {
int a = 3; //创建一个普通的整型变量 存3这个常量
int* b; //创建一个一重指针变量 存的是a变量的地址
b = &a;
int** c; //创建一个二重指针变量 存的是b变量的地址
c = &b;
printf("a的地址:%d\n",&a); //打印a的地址 0x123
printf("a的内容:%d\n",a); //打印a空间的内容 3
printf("b的地址:%d\n",&b); //0x456
printf("b的内容:%d\n",b); //0x123
printf("拿着b的内容去找变量a:%d\n",*b); //3
printf("c的地址:%d\n",&c); //0x789
printf("拿着c的内容去找变量b:%d\n",*c); //0x123
printf("拿着c的内容去找变量b,拿着b的内容去找变量a:%d\n",**c); //3
//printf("%d\n",*a);
printf("%d\n",*&*c); //0x123
printf("%d\n",&*&**&c); //0x456
}

结果如下

a的地址:6422300
a的内容:3
b的地址:6422296
b的内容:6422300
拿着b的内容去找变量a:3
c的地址:6422292
拿着c的内容去找变量b:6422300
拿着c的内容去找变量b,拿着b的内容去找变量a:3
6422300
6422296

数据类型

在Java当中,数据类型主要分为两大类:

  • 基本数据类型:在变量的空间中存储数据

  • 整形

    • byte 1字节 2^8 256 -128~127 -2^7 ~ 2^7 - 1
    • short 2字节 2^16 65536 -32768~32767 -2^15 ~ 2^15 - 1
    • int 4字节
    • long 8字节
  • 浮点型

    • float 4字节
    • double 8字节
    • 字符类型
      • char 2字节
    • 布尔型
      • boolean 不确定
注:在常量中,整型常量默认int类型,小数常量默认是double类型
布尔类型,如果是单一变量的话,在JVM中true被认为是1 false被认为是0 所以是4字节存
如果是布尔类型数组的话,在JVM中true和false被认为是byte类型 1字节
  • 引用数据类型:数据是在堆内存中存储,变量仅仅存放的是数据在堆内存中的地址
    • 字符串
    • 数组
    • 对象
在Java中,但凡存储在堆内存中的数据,统称为对象

运算符

算数运算符
算数运算 符含义备注
+加法1+2=3 如果加号左右有字符串 则加号为连接符
-减法3-2=1
*乘法3*2=6
/除法3/2=1 3.0/2=1.5 如果除号两边都是整数 结果为整数;有小数 结果为小 数
%取余9%5=4 注意一点,如果前或后为负数(取余看被除数 取商看除数)
a++后置自增a自身加一,使用原来的值
++a前置自 增a自身加一,使用加之后的值
a–后置自 减a自身减一,使用原来的值
–a前置自 减a自身减一,使用加之后的值
        int A=2;
        A*=2+9;
        System.out.println(A);#22
运算符优先级
优先级运算符名称或含义使用形式结合方向说明
1*[]*数组下标数组名[常量表达式]左到右
*()*圆括号(表达式)/函数名(形参表)
*.*成员选择(对象)对象.成员名
*->*成员选择(指针)对象指针->成员名
2*-*负号运算符-表达式*右到左*单目运算符
*~*按位取反运算符~表达式
*++*自增运算符++变量名/变量名++
*–*自减运算符–变量名/变量名–
***取值运算符*指针变量
*&*取地址运算符&变量名
*!*逻辑非运算符!表达式
*(**类型**)***强制类型转换(数据类型)表达式
*sizeof*长度运算符sizeof(表达式)
3*/*表达式/表达式左到右双目运算符
***表达式*表达式
*%*余数(取模)整型表达式%整型表达式
4*+*表达式+表达式左到右双目运算符
*-*表达式-表达式
5*<<*左移变量<<表达式左到右双目运算符
*>>*右移变量>>表达式
6*>*大于表达式>表达式左到右双目运算符
*>=*大于等于表达式>=表达式
*<*小于表达式<表达式
*<=*小于等于表达式<=表达式
7*==*等于表达式==表达式左到右双目运算符
*!**=***不等于表达式!= 表达式
8*&*按位与表达式&表达式左到右双目运算符
9*^*按位异或表达式^表达式左到右双目运算符
10*|*按位或表达式|表达式左到右双目运算符
11*&&*逻辑与表达式&&表达式左到右双目运算符
12*||*逻辑或表达式||表达式左到右双目运算符
13*?😗条件运算符表达式1?表达式2: 表达式3*右到左*三目运算符
14*=*赋值运算符变量=表达式*右到左*
*/=*除后赋值变量/=表达式
*=**乘后赋值变量*=表达式
*%=*取模后赋值变量%=表达式
*+=*加后赋值变量+=表达式
*-=*减后赋值变量-=表达式
*<<=*左移后赋值变量<<=表达式
*>>=*右移后赋值变量>>=表达式
*&=*按位与后赋值变量&=表达式
*^=*按位异或后赋值变量^=表达式
*|=*按位或后赋值变量|=表达式
15*,*逗号运算符表达式,表达式,…左到右
赋值运算符

+= 加法赋值 a+=3 相当于 a=a+3

注意 赋值运算符只能用在变量身上

比较运算符

运算的结果为布尔类型

  • / >大于
  • / < 小于
  • / >= 大于等于
  • / <= 小于等于
  • / != 不等于
逻辑运算符
  • & 单与
  • | 单或
  • ^ 异或
  • ! 非、
  • && 双与
  • || 双或
public class Sample {
public static void main(String[] args) {
int x = 0;
int y = 0;
System.out.println(x++ > 0 & y++ > 0);
System.out.println(x);
System.out.println(y);
x = 0;
y = 0;
System.out.println(x++ > 0 && y++ > 0);
System.out.println(x);
System.out.println(y);
//&& 如果左边为假 则右边不用执行
//|| 如果左边为真 则右边不用执行
//相同为假 不同为真
System.out.println(true ^ true);
System.out.println(true ^ false);
System.out.println(false ^ false);
System.out.println(false ^ true);
}
}
位运算符
  • & 位与
  • | 位或
  • ^ 位异或
  • />> 右移
  • << 左移
public class Sample {
public static void main(String[] args) {
int x = 7;
int y = 12;
System.out.println(x & y);
/*
0111
1100 &
0100 4
*/
System.out.println(x | y);
/*
0111
1100 |
1111 15
*/
System.out.println(x ^ y);
/*
0111
1100 ^
1011 11
*/
System.out.println(x << 3);
/*
0111
0111000
x * 2^3
*/
System.out.println(56 >> 2);
/*
111000
1110
56 / 2^2
*/
}
}

注意 当 用 i<<1+1;时 系统会认为 i<<2;

public class weiyi{
    public static void main(String []args){
        int i=1;
        i<<=1+1;
        System.out.println(i);//4
        i+=1;
        System.out.println(i);//5
         i=1;
        i<<=1;
        i+=1;
        System.out.println(i);//3
    
    }
}
三目运算符

​ 数据类型 变量名 = 布尔表达式?值1:值2;

 int number = 10 % 2 == 0? 10 : 2;
补充:变量交换问题
int a = 3;
int b = 7;

方法一:

int c = a;
a = b;
b = c;
System.out.println(a);
System.out.println(b);

方法二

a = a + b;
b = a - b;
a = a - b;
System.out.println(a);
System.out.println(b);

方法三

a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println(a);
System.out.println(b);

第三章 流程控制语句

if条件语句

单分支if语句

if(布尔类型表达式){
语句组;
}

双分支if-slse语句

if(布尔类型表达式){
语句组;
}else

多分支 if -else 语句

if (布尔表达式1) {
语句组A;
} else if (布尔表达式2) {
语句组B;
} else if (布尔表达式3) {
语句组C;
} else {
语句组D;
}

switch分支语句

与if分支语句一样,都是对条件的判断 。switch一般用在条件较多的情况下,但是有一个重要的细节,if语言可以对区间值或固定值进行判断,switch只能对固定值进行判断

switch(变量){
case1:
语句组A:
break;
case2:
语句组B;
break;
.......
case 值n: //if (变量==值n) {语句组N;}
语句组N;
default: // else {语句组N+1;}
语句组N+1;
break;
}

switch中的一些使用细节

  • switch所传入的变量,char,byte,short,int,String或者枚举类型
  • 值1,值2,一直到值n,这几个值必须是同一个数据类型的
  • 当变量匹配的相关case的值的时候,执行case中的语句,直到遇到break结束,如果该case语句 中没有break,则继续向下执行,直到遇到另外一个break结束。

for循环语句

循环主要解决具有规律性的且具有重复性的代码问题,避免程序冗余

循环四要素

  1. 循环的初始化:循环的第1次执行从哪里开始
  2. 循环的继续条件:循环从当前轮是否向后执行下一轮
  3. 循环体:需要被循环执行的部分
  4. 循环的步长、周期:当前循环到下一轮循环之间的变化 我们常见的循环问题可以分为两大类:
    1. 已知循环次数的 一般用for语句做
    2. 未知循环次数但是已知循环结束条件 一般用while语句做
for (1循环的初始化;2.循环的继续条件;4.循环的步长) {
3.循环体
}
1-2-3-4-2-3-4-2-3-4-2不满足则结束循环

for循环演示

import java.util.Scanner;
public class Sample {
public static void main(String[] args) {
/*
*****
*/
for (int i = 1; i <= 5; i++) {
System.out.print("*");
}
System.out.println();
System.out.println("=============================");
/*
*****
*****
*****
*****
*/
for (int j = 1; j <= 4; j++) {
for (int i = 1; i <= 5; i++) {
System.out.print("*");
}
System.out.println();
}
System.out.println("=============================");
/*
*
**
***
****
*****
******
*******
*/
for (int line = 1; line <= 7; line++) {
for (int i = 1; i <= line; i++) {
System.out.print("*");
}
System.out.println();
}
System.out.println("=============================");
/*
******
*****
****
***
**
*
*/
for (int line = 6; line >= 1; line--) {
for (int i = 1; i <= line; i++) {
System.out.print("*");
}
System.out.println();
}
System.out.println("=============================");
/*      i j
*       1 1
**      2 1 2
***     3 1 2 3
****    4 1 2 3 4
*****   5 1 2 3 4 5
******  6 1 2 3 4 5 6 j <= i
*****   7 1 2 3 4 5
****    8 1 2 3 4
***     9 1 2 3
**      10 1 2
*       11 1 j <= 12 - i
j <= i && j <= 12 - i
*/
for (int i = 1; i <= 11; i++) {
for (int j = 1; j <= i && j <= 12 - i; j++) {
System.out.print("*");
}
System.out.println();
}
System.out.println("=============================");
/*     i |i - 6|
     * 1 -5
    ** 2 -4
   *** 3 -3
  **** 4 -2
 ***** 5 -1
****** 6 0
 ***** 7 1
  **** 8 2
   *** 9 3
    ** 10 4
     * 11 5
*/
for (int i = 1; i <= 11; i++) {
for (int k = 1; k <= Math.abs(i - 6); k++) {
System.out.print(" ");
}
for (int j = 1; j <= i && j <= 12 - i; j++) {
System.out.print("* ");
}
System.out.println();
}
System.out.println("=============================");
/*                j
     *           1
    * *         1 2
   *   *       1 2 3
  *     *     1 2 3 4
 *       *   1 2 3 4 5
*         * 1 2 3 4 5 6
 *       *   1 2 3 4 5
  *     *     1 2 3 4
   *   *       1 2 3
    * *         1 2
     *           1
j == 1 j == i j + i == 12
*/
for (int i = 1; i <= 11; i++) {
for (int k = 1; k <= Math.abs(i - 6); k++) {
System.out.print(" ");
}
for (int j = 1; j <= i && j <= 12 - i; j++) {
if (j == 1 || j == i || j + i == 12) {
System.out.print("* ");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}

while循环语句

while循环主要用于解决循环次数未知,但循环结束条件已知的情况。

while其实和for循环是可以相互转换的,是因为都逃不开循环四要素

for (int i = 1; i <= 5; i++) {
System.out.println(i);
}
可以转换为while循环
int i = 1;
while (i <= 5) {
System.out.println(i);
i++;
}

while的语法格式

1.循环的初始化
while (2.循环继续条件) {
3.循环体
4.循环的步长、周期
}

break、continue跳转语句

break在循环语句中叫做终止语句,终止的是break最近的一层循环

continue在循环语句中叫做跳过语句,跳过本次循环开启下一轮循环

public class Sample {
public static void main(String[] args) {
for(int j=0;j<2;j++){
    for (int i = 1; i <= 5; i++) {
if (i == 3) {
break;
} else {
System.out.println(i);
}
}
}
//结果 1 2 1 2
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue;
} else {
System.out.println(i);
}
}
//结果 1 2 4 5
}
}

第四章 常用类

Math类

Math类是用于数学计算的一个工具类

对于工具类而言,里面的大部分成员都是静态的static

自带常量
  • static double E;自然对数
  • static double PI;圆周率
取整方法
  • static double cell(double a);向上取整
  • static double floor(double a);向下取整
  • static long round(double a);四舍五入
三角函数
  • static double sin(double a):正弦函数 参数是弧度值
  • static double cos(double a):余弦函数
  • static double tan(double a):正切函数
  • static double toDegrees(double a):将弧度转角度
  • static double toRadians(double angles):将角度转弧度
  • static double asin(double a):反正弦函数
  • static double acos(double a):反余弦函数
  • static double atan(double a):反正切函数
‘指数函数
  • static double pow(double a, double b):求a的b次幂
  • static double sqrt(double a):求a的平方根
  • static double cbrt(double a):求a的立方根
其他方法
  • static double abs(double a):求a的绝对值
  • static double hypot(double deltX, double deltY):返回 两点间距离
  • static double max(a,b):返回a和b之间的最大值
  • static double min(a,b):返回a和b之间的最小值
  • static double random():返回[0,1)之间的随机小数
用法
public class Sample {
public static void main(String[] args) {
System.out.println(Math.E);//2.718281828459045
System.out.println(Math.PI);//3.141592653589793
System.out.println(Math.ceil(3.1));//4.0
System.out.println(Math.ceil(3.9));//4.0
System.out.println(Math.ceil(-3.1));//-3.0
System.out.println(Math.ceil(-3.9));//-3.0
System.out.println(Math.floor(3.1));//3.0
System.out.println(Math.floor(3.9));//3.0
System.out.println(Math.floor(-3.1));//-4.0
System.out.println(Math.floor(-3.9));//-4.0
System.out.println(Math.round(3.1));//3
System.out.println(Math.round(3.9));//4
System.out.println(Math.round(-3.1));//-3
System.out.println(Math.round(-3.9));//-4
System.out.println(Math.sin(Math.PI/6));//0.4999999999999999
System.out.println(Math.cos(Math.PI/3));//0.5000000000000001
System.out.println(Math.tan(Math.PI/4));//0.9999999999999999
System.out.println(Math.toDegrees(Math.PI/2));//90.0
System.out.println(Math.toRadians(90));//1.5707963267948966
System.out.println(Math.cbrt(8));//2.0
System.out.println(Math.hypot(0 - 1, 0 - 1));//1.4142135623730951
}
}

Scanner类

主要用于负责数据输入的类,底层是和IO流相关。

需要先导包

导包方法: import java.util.Scanner;

输入数据前提方法Scanner xxxx = new Scanner(System.in);

获取方法: 类型 line = input.方法();

方法
  • String next():获取直到遇到空格为止的一个字符串
  • String nextLine():获取直到遇到回车为止的一个字符串
  • int nextInt():获取下一个整数
  • byte short long double nextDouble();获取下一个double类型数
  • boolean nextBoolean();获取下一个booleat类型数
  • float nextFloat();获取下一个float类型数
用法
import java.util.Scanner;
public class Sample {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("输入一句话:");
String line = input.nextLine();
System.out.println(line);
System.out.print("输入三个单词:");
String word1 = input.next();
String word2 = input.next();
String word3 = input.next();
System.out.println(word1);
System.out.println(word2);
System.out.println(word3);
}
}

String类

String是一个类,它描述的是字符串。在Java代码当中,所有字符串常量(字符串字面量)都是 String类的一个实例对象。并且,字符串一旦创建,则不可修改! 不可修改其长度,不可修改其内容 。所 以将来对字符串内容的改变,不能在原地改,只能重新创建一个字符串。

public class Sample {
public static void main(String[] args) {
String s1 = "abc";
String s2 = "ab" + "dc";
//上述代码一共有几个字符串?
//四个"abc" "ab" "dc" "abdc"
}
}
创造相关
		String str1="字符串1";
        String str2=new String("字符串2");
        String str3=new String();
获取相关
  • char charAt(int index):获取指定角标index处的字符
  • int indexOf(int ch):获取指定字符(编码)在字符串中第一次(从左到右)出现的地方返回的是 角标。如果是-1 表示不存在
  • int lastIndexOf(int ch):获取指定字符(编码)在字符串中第一次(从右到做)出现的地方返回的 是角标 int indexOf(String str):获取指定字符串在本字符串中第一次(从左到右)出现的地方返回的是 角标
  • int lastIndexOf(String str):获取指定字符串在本字符串中第一次(从右到左)出现的地方返回 的是角标
  • int length():获取字符串的长度(字符的个数)
  • String[] split(String regex):将字符串按照regex的定义进行切割(regex指的是正则表达式)
  • String substring(int beginIndex):截取一段子字符串,从beginIndex开始到结尾
  • String substring(int beginIndex, int endIndex):截取一段子字符串,从beginIndex开始到 endIndex(不包含)
  • 当beginIndex为负值或者大于字符长度报错
判断相关
  • int compareTo(String anotherString):按照字典顺序比较两个字符串的大小

  •     String s="AB";
        String s1="BBB";
    System.out.println(s.compareTo(s1));
    //-1
             s="BBD";
             s1="BBB";
       System.out.println(s.compareTo(s1));
    //2
            s="BBD";
            s1="C";
       System.out.println(s.compareTo(s1));
    
    
  • boolean contains(String another):判断当前字符串中是否包含指定字符串

  • another boolean equals(String another):比较当前字符串与指定字符串的内容是否相同

  • another boolean equalsIgnoreCase(String another):比较当前字符串与指定字符串的内容是否相同 (忽略大小写)

  • boolean isEmpty():判断当前字符串是否为空,length() == 0

  • boolean startsWith(String prefix):判断该字符串是否以prefix开头

  • boolean endsWith(String suffix);判断该字符是否以suffix结尾

修改相关
  • String toLowerCase():将字符串中所有的英文字母全部变为小写
  • String toUpperCase():将字符串中所有的英文字母全部变为大写
  • String trim():将字符串中两端的多余空格进行删除
  • String replace(char oldCh,char newCh):将字符串中oldCh字符替换成newCh字符
  • concat(String str)字符串后面添加 返回新的字符串
转化相关

getBytes 返回Bytes类型数组

            String str="哈哈哈哈哈啥事";
        byte[] A= new byte[0];
        try {
            A = str.getBytes("GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println(Arrays.toString(A));

        String str2= null;
        try {
            str2 = new String(A,"GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        System.out.println(str2);

StringBuilder

介绍

线程不安全 但是快

方法

append( )

添加

insert( 插入位置,str)

插入

replace(替换起始,替换结束位置+1,替换的str)

替换

delete(删除起始,删除结束位置+1)

删除

tostring()

转换成字符串

reverse()

反转

StringBuffer

和StringBuilder方法差不多

但是StringBuffer线程安

Character类

Character它是char基本数据类型的 包装类 ,有这么几个静态方法我可目前可以使用到的

  • static boolean isDigit(char ch):判断字符是否是数字
  • static boolean isLetter(char ch):判断字符是否是字母
  • static boolean isLetterOrDigit(char ch):判断字符是否是数字或字母
  • static boolean isLowerCase(char ch):判断是否是小写字母
  • static boolean isUpperCase(char ch):判断是否是大写字母
  • static boolean isSpaceChar(char ch):判断是否空白字母(空格 制表符 回车)

格式化输出

printf s为字符 d为数字

System.out.printf("%-10s",“abc”); //输出10列,左对齐(-号表示左对齐)
System.out.printf("%8d",23); //输出8列, 右对刘

日期函数

long a= System.currentTimeMillis();

获取毫秒数

第五章 函数

函数的概念

函数的定义就是指一段具有独立功能的代码,减少代码冗余,提高程序的利用率和效率。

如何去定义函数

  1. 需要一个封闭的空间,将这段独立性的代码进行封装,用一对大括号
  2. 需要对每一个封闭的空间进行命名,函数名
  3. 函数所需要的一些原始数据
  4. 函数所产生的一些结果数据

函数的语法格式

修饰符 函数类型 返回值类型 函数名(数据类型 数据1,数据2,数据3){
    独立功能的代码片段;
    return 函数的结果;
}
  • 修饰符 :指的是函数的访问权限,public private 默认 protected
  • 函数类型:函数的分类,本地函数native,静态函数 static ,同步函数synchronized
  • 返回值类型:指的就是函数计算结果的数据类型 如果函数没有返回值 则为void
  • 函数名:就是函数的名称
  • 参数列表:指的是外界向函数传入的数据(实际参数),由这些参数变量进行接收(形式参 数)
  • 函数体:具有独立功能的代码片段;
  • return:仅仅表示函数结束!如果函数有返回值,则return后跟返回值;如果没有返回值,则 return可以不写,但是是存在的(隐藏的 在最后一行)

根据形参和返回值来看,函数有如下几个分类

  • 有参数有返回值

​ 求三个数字当中的最大值

public class Sample {
public static void main(String[] args) {
int max = getMax(1,2,3);
System.out.println(max);
}
public static int getMax (int a , int b , int c) {
/*
if (a >= b && a >= c) {
return a;
}else if (b >= a && b >= c) {
return b;
}else {
return c;
}
*/
if (a >= b && a >= c) {
return a;
}
if (b >= a && b >= c) {
return b;
}
if (c >= a && c >= b) {
return c;
}
return -10000;
}
  • 有参数无返回值

  • 无参数有返回值

获取当前时间的字符串

public class Sample {
public static void main(String[] args) {
String currentTime = getTime();
System.out.println(currentTime);
}
public static String getTime() {
//1.获取总毫秒数
long millis = System.currentTimeMillis();
//2.计算总秒数
long seconds = millis / 1000;
//3.计算总分钟数
long minutes = seconds / 60;
//4.计算总小时数
long hours = minutes / 60;
//5.计算当前小时数
long currentHours = hours % 24;
//6.计算当前分钟数
long currenrMinutes = minutes % 60;
//7.计算当前秒数
long currentSeconds = seconds % 60;
return currentHours + ":" + currenrMinutes + ":" +currentSeconds;
}
}
  • 无参数无返回值

其实就是在函数中直接输出想要获取的信息

函数的运行原理

函数的运行是基于栈运行的

栈:是一种先进后出的容器,我们这里面所说的栈是指JVM中的栈内存空间

每一个函数,叫做栈帧,栈帧中所包含的内容有函数的定义,参数列表,函数的执行内容代码

每一个函数要运行,就相当于这个栈帧进入到栈内存中-入栈

如果一个函数即将结束,将这个栈帧从栈顶移出-出栈

如果栈内存中有多个栈帧,运行的是最上面的栈帧,底下的栈帧暂停运行,直到该栈帧为栈顶元素

比如:主函数先进栈,开始逐行运行,如果执行到第n行,调用另外一个函数A,则主函数在第n行 暂停运行,将另一个函数A的栈帧入栈,再继续逐行运行,直到函数A的内容执行完毕,函数A出栈,主 函数接着从第n行继续向下执行。以此类推。

函数重载

同一个类中可以出现多个同名函数,这个现象就叫做函数的重载(overload)

如何区分是否重载

  1. 前提必须是同名
  2. 返回值类型无关(返回值类型只和函 数的计算功能相关)
  3. 和权限也没有关系
  4. 和形式参数的名称也无关
  5. 只和形式参数的数据类型有关 (数量,排列组合)
public static void show(int a ,float b ,char c){}

下列哪些是该函数的重载:

  • int show(int x, float y, char z) :不算重载 数据类型都是int float char
  • void show(float b,int a,char c):算重载,顺序不一样float int char
  • void show(int a,int b,int c):算重载,顺序不一样int int int
  • double show():算重载,参数不一样

寻找重载的流程

  1. 看是否有确切的参数定义匹配,int int 找 int int
  2. 看是否有可兼容的参数定义匹配,int int找double double或int double或double int
  3. 如果可兼容的参数定义匹配较多,会报引用确定报错 引用不明确

即 如果 int int既可以找 double int也可以找int double 引用不明确会报错

函数可变参数
public static void show(int a ,int ...b){
    for(int i:b){
		System.out.println(i);
    }
}

定义:

从JDK1.5之后,java提供了可变参数(variable arguments,varargs)。
可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理。
写法:
变量类型…变量名;
String…name

注意:

…位于变量类型和变量名之间,前后有无空格都可以;

一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。即使不同类型

调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。

注意不能让调用的方法可以与两个可变参数匹配 可以不同类型

一个方法里面不可用两个可变参数 即使不同类型

传入null时并不是只含有一个null元素的数组,而是null

可变参数优先级为最后

不可使用两个重载可变参数

非单独传入时候为数组形式

单独时候为数值

函数的递归

定义

函数的递归就是指函数自身调用自身。

相对而言,从内存的角度而言,函数如果过多的自我调用,势必会对内存不友好,占用过多

通常来讲,同样的问题用递归写要比用迭代写代码量较少

写递归时,一定要先确定递归结束条件-递归边界

案例

递归实现斐波那契数列

public class Sample {
public static void main(String[] args) {
/*
1 1 2 3 5 8 13 21 34 55 ...
1 x=1,x=2
f(x) =
f(x-1) + f(x-2) x>2
f(5)
f(4) f(3)
f(3) f(2) f(2) f(1)
f(2) f(1)
*/
//递归O(2^n)
System.out.println(f(35));
//迭代O(n)
System.out.println(fibo_it(35));
}
public static int fibo_it(int x) {
if (x == 1 || x == 2) {
return 1;
}
/*
1 1 2 3
c
a b
*/
int a = 1;
int b = 1;
int c = 0;
for (int i = 3; i <= x; i++) {
c = a + b;
a = b;
b = c;
}
return c;
public static int f(int x) {
if (x == 1 || x == 2) {
return 1;
}else {
return f(x-1) + f(x-2);
}
}
}

汉诺塔问题

public class Demo81 {
/*
前4个 x->z
前3个 x->y
前2个 x->z
前1个 x->y
第2个 x->z
前1个 y->z
第3个 x->y
前2个 z->y
前1个 z->x
第2个 z->y
前1个 x->y
第4个 x->z
前3个 y->z
前2个 y->x
前1个 y->z
第2个 y->x
前1个 z->x
第3个 y->z
前2个 x->z
前1个 x->y
第2个 x->z
前1个 y->z
*/
public static void main(String[] args) {
String x = "x";
String y = "y";
String z = "z";
hano(3,x,y,z);
//前3层从 x->z
//前2层从 x->y
}
public static void hano(int level,String begin,String mid,String end) {
if (level == 1) {
System.out.println(begin+"->"+end);
} else {
//前level-1层
hano(level - 1,begin,end,mid);
System.out.println(begin+"->"+end);
//前leve1-1层
hano(level - 1,mid,begin,end);
   }
  }
}

第六章 数组

数组的概念及定义

数组概念

数组主要用于解决大量数据计算和存储的问题

比如:输入100个数字,统计其中的最大值和最小值并计算平均值,创建100个变量,会有一堆if else语句,比较麻烦。

数组是Java提供的一种最简单的数据结构,可以用来存储一个元素 个数固定 且 类型相同 的有序 集。

数组在内存中的情况

栈:主要用于运行函数的内存

堆:主要用于存储数据对象的内存

每一个数组而言,都是存在堆内存当中,每一个数组都是一个对象

注意

数组本质上就是在堆内存中一系列地址连续且空间大小相等的存储空间(变量),每一个存 储空间用来存储数据(基本,引用)

数组是在堆内存中存储,称之为是一个对数对象,并且在堆内存中存储的数据都有 默认初始 化 的流程。所以数组创建之初,每一个存储空间里面都会被JVM初始化该数据类型对应的零值。

数组的地址是连续的,所以通过公式:An=A1+(n-1)*d可以快速访问到其他的元素,所以对于 数组而言查找元素比较快的。将元素的真实物理地址转换成对应的角标获取元素。

如何来调用数组呢?

通过一个变量存储该数组在堆内存当中的首元素的地址。 当数组一旦定义出来,其长度不可变,存储空间的内容是可变的 所以我们在定义数组的时候,要么把长度固定,要么直接输入相关的元素。

数组定义
数组的定义方式

创建一个指定长度且指定数据类型的一维数组,名称为数组名,虽然没有指定元素,但是会有默认值
java 基本数据类型初始值 (默认值)

常用的数据类型
1 int类型定义的数组,初始化默认是0
2、String类型定义的数组,默认值是null
3、char类型定义的数组,默认值是0对应的字符

一维数组定义

数据类型[] 数组名 = new 数据类型[长度];
创建一个指定元素且指定数据类型的一维数组,名称为数组名,虽然有指定元素,还是有默认初始化这个步骤的!
数据类型[] 数组名 = new 数据类型[]{数据1,数据2,…,数据n};
数据类型[] 数组名 = {数据1,数据2,…,数据n};
数据类型 数组名[] = new 数据类型[长度];

		int[] arrA = new int[1];
        int arrB[] = new int[1];
        int[] arrC = new int[]{1};//该方法可以匿名
        int[] arrD={1};
二维数组的定义

和一维数组类似 只是[] 有两个
在定义二维数组的时候 [] 位置可以放在数据类型和数组名之后 数量总和等于二
常用的几种定义方式有
数据类型[][] 数组名 = new 数据类型[][]{{数据1,数据n},{数据1,数据2,…,数据n},…,{数据1,…,数据n}};
数据类型[][] 数组名 = {{数据1,数据n},{数据1,数据2,…,数据n},…,{数据1,…,数据n}};
数据类型[][] 数组名 = new 数据类型[行长度][列长度];

        int[][] arrE = new int[1][1];
        int[] arrF[] = new int[1][1];
        int arrG[][] = new int[1][1];
        int[][] arrH = {{1,2},{2,3,4}};
        int[][] arrI = new int[][]{{1,2},{2,3,4}};
一维数组的定义
定义
//创建一个指定长度且指定数据类型的一维数组,名称为数组名,虽然没有指定元素,但是会有默认值
数据类型[] 数组名 = new 数据类型[长度];
//创建一个指定元素且指定数据类型的一维数组,名称为数组名,虽然有指定元素,还是有默认初始化这个步骤的!
数据类型[] 数组名 = new 数据类型[]{数据1,数据2,...,数据n};
数据类型[] 数组名 = {数据1,数据2,...,数据n};

方法

arr.length 一维数组的长度

Arrays.copyOf(arr,arr.length*2);返回拷贝扩容

二维数组的定义
定义

二维数组,在表现形式上就是一个表格,在操作表格的时候以行列来操作

01
00.00.1
11.01.1
22.02.1

所谓的二维数组,本质上就是一个一维数组,只不过该一维数组里面的元素是另一个一维数组而已

public class Sample {
public static void main(String[] args) {
//数据类型[][] 矩阵名 = new 数据类型[row][col];
int[][] matrix = new int[3][2];
/*
数据类型[][] 矩阵名 = new 数据类型[][] {
{...},
{...},
{...}
};
数据类型[][] 矩阵名 = {
{...},
{...},
{...}
};
*/
int[][] matrix2 = {
{1,2,3},
{4,5,6},
{7,8,9}
};
for (int i = 0; i < matrix2.length; i++) {
for (int j = 0; j < matrix2[i].length; j++) {
System.out.print(matrix2[i][j] + " ");
}
System.out.println();
}
int[][] matrix3 = {
{1},
{1,2,3},
{1,2,3,4},
{7,6,5,4,3,2,1}
};
for (int i = 0; i < matrix3.length; i++) {
for (int j = 0; j < matrix3[i].length; j++) {
System.out.print(matrix3[i][j] + " ");
}
System.out.println();
}}}
方法

arr.length 二维数组的行数

arr.[0]表示另一个一维数组

arr[0].length 第一个一维数组的长度

常用数组操作

数组遍历问题
public class Sample {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5,6,7,8,9};
//String str str.length()-函数
//int[] arr arr.length-属性
for (int i = 0; i < arr.length; i++) {
arr[i] = arr[i] * 10;
System.out.println(arr[i]);
}
//通过角标遍历 可以在遍历的过程中对指定的元素进行修改
//foreach遍历 主要针对的是一些可迭代对象 Iterable
/*
for (数据类型 变量名 : 可迭代容器) {
}
*/
for (int num : arr) {
//num -> arr[i]
num = num / 10;
System.out.println(num);
}
//这种遍历方式 只能获取元素,不能修改元素
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}

方法

获取数组的长度

arr.length
如果是一位数组 直接获取数组长度
如果是二维数组
先获取某一列然后再获取数组某一列的长度
直接使用获取的是数组的行数
例子

一维数组
int[] arrA={1,2,3};
        System.out.println(arrA.length);//3
二维数组
        int[][] arrB = {{1, 2}, {2, 3, 4}};
        System.out.println(arrB.length);//2
        System.out.println(arrB[0].length);//2
        System.out.println(arrB[1].length);//3
打印数组

Arrays.toString(arr);

		int[] intArray = { 1, 2, 3, 4, 5 };
        String intArrayString = Arrays.toString(intArray);
        System.out.println(intArrayString);//[1, 2, 3, 4, 5]

因为在学习数据结构的时候会经常用到
所以 我把 具体代码写了出来

private static String toSring(int[] arr) {
        String arrs="[";
        for (int i = 0; i <arr.length ; i++) {
            arrs+=arr[i];
            if (i+1<arr.length){
                arrs+=",";
            }
        }
        arrs+="]";
        return arrs;
    }
数组扩容

注意 需要导包 import java.util.Arrays;

Arrays.copyOf(需要拷贝的数组名,拷贝后的长度);
返回拷贝扩容
拷贝后的长度如果小于原数组则只是截取部分
拷贝后的长度如果大于原数组 ,则多余部分为默认值
该方法并不会使原数组发生改变

        int[] arrA={1,2,3};
         System.out.println(Arrays.toString(arrA));//     [1,2,3]
        int[] arrB=Arrays.copyOf(arrA,arrA.length-1);
        System.out.println(Arrays.toString(arrB));[1,2]
        int[] arrC=Arrays.copyOf(arrA,arrA.length*2);
        System.out.println(Arrays.toString(arrC));//[1,2,3,0,0,0]
        System.out.println(Arrays.toString(arrA));//[1,2,3]

Arrays.copyOfRange(arr, int fromIndex, int toIndex);
复制数组范围为从fromIndex到(toIndex-1);

        int[] arrA={1,2,3};
        int[] arrB=Arrays.copyOfRange(arrA,1,3);
        System.out.println(Arrays.toString(arrB));//[2,3]
数组合并

System.arraycopy(arr, 1, arr2, 3, arr.length-1);
第一个元素 表示需要复制的原数组
第二个元素 代表从原数组的哪一个元素开始复制(下标)
第三个元素 目标数组
第四个元素 从目标数组的哪一个元素开始粘贴原数组的数据
第五个元素 复制原数组的长度是多少

        int[] arr= {0,1,2,3,4};
        int[] arr2= {10,20,30,40,50,60,70,80,90};
        System.arraycopy(arr, 1, arr2, 3, arr.length-1);
        System.out.println(Arrays.toString(arr2));
		//[10, 20, 30, 1, 2, 3, 4, 80, 90]

如果要合并两个数组
只需要先扩容然后复制

        int[] arr= {0,1,2,3,4};
        int[] arr2= {10,20,30,40,50,60,70,80,90};
        arr2=Arrays.copyOf(arr2,arr.length+arr2.length);
        System.arraycopy(arr, 0, arr2, arr2.length-arr.length, arr.length);
        System.out.println(Arrays.toString(arr2));
        //[10, 20, 30, 40, 50, 60, 70, 80, 90, 0, 1, 2, 3, 4]
数组排序

Arrys.sort(Object[] arr)
对指定对象数组根据其元素的自然顺序进行升序排列。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。
注意 :该方法是在原数组上进行修改

		int[] arrA={3,2,1};
        Arrays.sort(arrA);
        System.out.println(Arrays.toString(arrA));//[1,2,3]

Arrys.equals(long[] a, long[] a2)
如果两个指定的 long 型数组彼此相等,则返回 true。如果两个数组包含相同数量的元素,并且两个数组中的所有相应元素对都是相等的,则认为这两个数组是相等的。换句话说,如果两个数组以相同顺序包含相同的元素,则两个数组是相等的。同样的方法适用于所有的其他基本数据类型(Byte,short,Int等)。

        int[] arrA = {1, 2, 3};
        int[] arrB = {4, 5, 6};
        int[] arrC = {1, 2, 3};
        System.out.println(Arrays.equals(arrA,arrB));//false
        System.out.println(Arrays.equals(arrA,arrC));//true
数组查询

Arrays类的binarySearch()方法—用二分搜索法搜索指定数组—返回要搜索元素的索引值—适用于各种类型数组

-----必须在调用之前对数组进行排序(通过sort()方法)—如果数组包含多个带有指定值的元素,则无法保证找到的是哪一个

1)Arrays.binarySearch(Object[], Object key);

如果key包含在数组中,返回索引值;否则返回“-1”或“-”(插入点)

插入点:搜索键将要插入数组的那一点,即第一个大于此键的元素索引

2)Arrays.binarySearch(Object[], int fromIndex,int toIndex,Object key);

搜索范围为从fromIndex到(toIndex-1)

        int[] arrA={1,2,4,5,6};
        Arrays.sort(arrA);   //必须先将数组排序
        System.out.println(Arrays.binarySearch(arrA,1));//0
        System.out.println(Arrays.binarySearch(arrA,3));//-3
        System.out.println(Arrays.toString(arrA));

数组最值问题
public class Sample {
public static void main(String[] args) {
int[] arr = new int[]{3,6,8,2,9,4,5,1,7};
int min = arr[0];
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
}
if (arr[i] > max) {
max = arr[i];
}
}
System.out.println(max);
System.out.println(min);
}
}

数组扩容问题
public class Sample {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
arr = add(arr,6);
arr = add(arr,6);
arr = add(arr,6);
arr = add(arr,6);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}//123456666
//在指定的数组arr中添加元素element
public static int[] add(int[] arr, int element) {
int[] newArr = new int[arr.length + 1];
for (int i = 0; i < arr.length; i++) {
newArr[i] = arr[i];
}
newArr[newArr.length - 1] = element;
return newArr;
}
}

方法扩容

System.arraycopy(arr,1,arg2,3,arr.length-1);

原数组 原数组开始复制位置 复制到的数组 后数组复制位置 原数组长度

int[] arg3= Arrays.copyOf(arr,arr.length*2);

int[] arr={1,2,3,4,5};
int[] arg2={1,1,1,1,1,1,1,1,1};
System.arraycopy(arr,1,arg2,3,arr.length-1);
for (int A:arg2){
    System.out.print(A+" ");
}//1 1 1 2 3 4 5 1 1  
System.out.println(" ");
int[] arg3= Arrays.copyOf(arr,arr.length*2);
for (int A:arg3){
    System.out.print(A+" ");
}// 1 2 3 4 5 0 0 0 0 0 
数组排序问题
选择排序算法

从小到大正方向获取

public class Sample {
//选择排序
public static void main(String[] args) {
int[] arr = {8,9,2,6,7,1,4,5,3};
for (int i = 0; i < arr.length - 1; i++) { //-1 n个数字没有第n轮
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
swap(arr,i,j);
}
}
}
print(arr);
}
//[1, 2, 3, 4, 5]
public static void print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length;i++) {
System.out.print(arr[i]);
if (i == arr.length - 1) {
System.out.println("]");
} else {
System.out.print(", ");
}
}
}
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}

冒泡排序算法

从大到小反方向获取

public class Sample {
//冒泡排序
	public static void main(String[] args) {
		int[] arr = {8,9,2,6,7,1,4,5,3};
		for (int i = 0; i <arr.length - 1; i++) {//-1 表示n个数字只有n-1轮
			for (int j = 0; j < arr.length - 1 - i; j++) {//-1 避免重复比较(当前最大和上一
轮最大)
				if (arr[j] > arr[j + 1]) {
					swap(arr,j,j+1);
				}
		}
	}
	print(arr);
	}
	public static void print(int[] arr) {
		System.out.print("[");
		for (int i = 0; i < arr.length;i++) {
			System.out.print(arr[i]);
			if (i == arr.length - 1) {
				System.out.println("]");
			} else {
				System.out.print(", ");
			}
		}
	}
	public static void swap(int[] arr, int i, int j) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
}
插入排序算法

从前到后逐个排序

public class Sample {
//插入排序
	public static void main(String[] args) {
		int[] arr = {8,9,2,6,7,1,4,5,3};
		for (int i = 1; i < arr.length; i++) {
			int e = arr[i];
			int j = 0;
			for (j = i; j > 0 && arr[j - 1] > e; j--) {
				arr[j] = arr[j - 1];
			}
			arr[j] = e;
		}
		print(arr);
	}
	public static void print(int[] arr) {
		System.out.print("[");
		for (int i = 0; i < arr.length;i++) {
			System.out.print(arr[i]);
			if (i == arr.length - 1) {
				System.out.println("]");
		} else {
				System.out.print(", ");
			}
		}
	}
}
计数排序算法

创建最大减去最小个空间 然后输入个数

public class Sample {
//计数排序
	public static void main(String[] args) {
		int[] arr = {-2,9,-1,12,8,-3,6,7,4,5,2,1,0,8,6,7,4,-3,-2,-1,-1,7};
		int min = arr[0];
		int max = arr[0];
		//O(n)
		for (int i = 1; i < arr.length; i++) {
			if (arr[i] < min) {
				min = arr[i];
			}
			if (arr[i] > max) {
			max = arr[i];
		}
	}
	int[] temp = new int[max - min + 1];
	//对应关系 index = number - min number = index 		+ min
	//O(n)
	for (int i = 0; i < arr.length; i++) {
		temp[arr[i] - min]++;
	}
	//temp[index] 表示index对应的数字number出现的次数
	int k = 0;
	//O(n)
	for (int index = 0; index < temp.length; index++) {
		while (temp[index] != 0) {
			arr[k] = index + min;	
			k++;
			temp[index]--;
		}
	}
	print(arr);
}
	public static void print(int[] arr) {
		System.out.print("[");
		for (int i = 0; i < arr.length;i++) {
			System.out.print(arr[i]);
			if (i == arr.length - 1) {
				System.out.println("]");
			} else {
					System.out.print(", ");
			}	
		}
	}
}
基数排序算法

个十百千位从小到大排序

import java.util.LinkedList;
public class Sample {
//基数排序
public static void main(String[] args) {
int[] arr = {102,203,321,13,12,78,96,34,37,28,6,8,5,6};
//1.先找到最大值 决定轮数
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
int radex = (max + "").length();
//2.创建十个桶 每一个桶是LinkedList
LinkedList<Integer>[] queues = new LinkedList[10];
for (int i = 0; i < queues.length; i++) {
queues[i] = new LinkedList<Integer>();
}
//3.进行数字分类和规整
//r=0个位 r=1十位 r=2百位...
for (int r = 0; r < radex; r++) {
//先按照r进行分类
for (int i = 0; i < arr.length; i++) {
int index = getIndex(arr[i],r);//获取数字的r位 返回该数字要去的桶的角标0~9
queues[index].offer(arr[i]);
}
//然后在重新规整到arr里
int k = 0;
for (int index = 0; index < queues.length; index++) {
while(!queues[index].isEmpty()) {
arr[k++] = queues[index].poll();
}
}
}
print(arr);
}
public static int getIndex(int number, int r) {
//123 r=0
//123 r=1
//123 r=2
int index = 0;
for (int i = 0; i <= r; i++) {
index = number % 10;
number /= 10;
}
return index;
}
public static void print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length;i++) {
System.out.print(arr[i]);
if (i == arr.length - 1) {
System.out.println("]");
} else {
System.out.print(", ");
}
}
}
}

二分查找算法

有一个前提,所查找的数据集必须是有序的(升序,降序)

public class Sample {
//二分查找
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9};
int min = 0;
int max = arr.length - 1;
int mid = (min + max) / 2;
int key = 10;
while (arr[mid] != key) {
if (key < arr[mid]) {
max = mid - 1;
}
if (arr[mid] < key) {
min = mid + 1;
}
if (min > max) {
mid = -1;
break;
}
mid = (min + max) / 2;
}
System.out.println(mid);
}
}
可变长参数列表

进入函数的时候创建一维数组

public class Sample {
public static void main(String[] args) {
show(1);
show(1,2,3);
show("hehe","lala","haha","xixi","heihei");
}
public static void show(int ... nums) {
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + " ");
}
System.out.println();
}
public static void show(String ... strs) {
for (int i = 0; i < strs.length; i++) {
System.out.print(strs[i] + " ");
}
System.out.println();
}
}

文件

file类

首先导入 io.file包

import java.io.File
创建文件夹

boolean mkdir()

File f=new File("路径")
f.mkdir()//创建目录文件夹  会返回是否创建如果已经存在会返回false

只能创建已有路径的 如果父文件夹不存在 则返回flase

创建子文件
File f=new File("c:\\1\\2\\3")
f.mkdirs()//创建目录文件夹  会返回是否创建如果已经存在会返回false
//且父子目录一起创建 如果父不存在会创建父文件
查看文件夹是否存在
File f=new File("c:\\1\\2\\3")
Boolean z=f.exists();//如果存在返回true不存在返回flase
获取文件名

getAbsolutePath()

获取文件名 无论f是否存在

File f=new File("c:\\1\\2\\3")
Boolean z=f.getAbsolutePath();//"c:\\1\\2\\3"

getName()

返回文件名但是不返回路径

File f=new File("c:\\1\\2\\3")
Boolean z=f. getName();//"3"
判断file是否是文件夹

isDirectory

判断file是否是文件夹

File f=new File("c:\\1\\2\\3")
Boolean z=f.isDirectory();//ture

判断file是否是文件

isFile

判断file是否是文件

是返回ture

否则返回flase 不存在也返回flase

File f=new File("c:\\1\\2\\3")
Boolean z=f.isFile();//flase
文件或者文件夹大小

length

返回是b

结果除以1024是kb

File f=new File("c:\\1\\2\\3");
long z=f.length();
查看隐藏文件

isHidden

判断一个文件或许文件夹是否隐藏文件如果是返回ture

File f=new File("c:\\1\\2\\3");
long z=f.isHidden();
删除文件或文件夹

delete

删除文件或文件夹如果是文件夹则必须为空

删除成功返回ture

File f=new File("c:\\1\\2\\3");
long z=f.delete;
修改文件名

renameTO(新file)

如果成功返回ture

File f=new File("c:aaa");
File f1=new File("c:bbb");
boolean f.renameTo(f1) 
文件夹列表

File[] listFiles()

File f=new File("C:\\")
File fs[]=f.listFiles();
for(File ff:fs){
    system.out.ff.getAbsolutePath()
}
    

跨平台之\

File.separator

相当于分隔符\ 可以跨平台使用

IO流

定义

使用时候需要导入io

InputStream

输入字节流(byte 8位)以内存为中心

Reader

字符输入流(char 1位)

读取内容

OnputStream

输出字节流(byte 8位)以内存为中心

Writr

字符输出流(char 1位)

写入内容

注;字节流可以操作字节也可以操作字符及二进制

字符流只能操作字符不能操作二进制

FileReader

(文件字符输入流)

注:因为方法构造器会返回异常 所以必须抛出异常

读取单个字符

D:\ccc.txt中内容为

ABC
import java.io.FileReader;
import java.io.IOException;

public class file {
    public static void main(String[] args) {
        try {
            FileReader f = new FileReader("D:\\ccc.txt");
            char z= (char) f.read();
            System.out.println(z);//A
            char zz= (char) f.read();
            System.out.println(zz);//B
            zz= (char) f.read();
            System.out.println(zz);//C
            zz= (char) f.read();
            System.out.println(zz);//-1          
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

注意 如果读取超过了文件长度 会返回-1

读取全部内容

利用read末尾返回值为-1去读取

import java.io.*;

public class file1 {
    public static void main(String[] args) {
        try {
            FileReader f=new FileReader(new File("d:\\ccc.txt"));
            int i;
            while ((i=  f.read())!=-1){
                System.out.print((char)i);
            }
            f.close();//关闭f
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

输出

ABC
读取一行
方法一

只需要在读取全部的时候加一个if判断即可

if((char)i=='\n') break;
                
import java.io.*;
public class file1 {
    public static void main(String[] args)  {
        try {
            FileReader f=new FileReader(new File("d:\\ccc.txt"));
            int i;
            while ((i=  f.read())!=-1){
                if((char)i=='\n') break;
                System.out.print((char)i);
            }
            f.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

文件夹一行最多1026个字符其中最后一个为/n

方法二

用装饰流BufferedReader bin=new BufferedReader(f);

去把FileReader包起来去获取 一行 且时间会比原流快很多

import java.io.*;
public class file3 {
    public static void main(String[] args) {
        File F=new File("d:\\ccc.txt");
        try {
            FileReader f=new FileReader(F);
            int i;
            BufferedReader bin=new BufferedReader(f);
            System.out.println(bin.readLine());
            f.close();//关闭f
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
读中文
BufferedReader r= new BufferedReader(new InputStreamReader(new FileInputStream(txt), "Utf-8"));
装饰流

BufferedReader —FileReader

BufferedWriter–FileWriter

BufferedInputStream—FileInputStream

BufferedOuputStream—FileOuputStream

包起来去获取 时间会比原流快很多

System

System.out 字节输出流

System.in 字节输入流

获取输入的一个
import java.io.*;
public class file4 {
    public static void main(String[] args) throws IOException {
        InputStream n= System.in;
        int Z=n.read();//每次只能读一个
        System.out.println(Z);
        Z=n.read();//所以多次读取
        System.out.println(Z);
    }
}
获取输入的全部

先用InputStreamReader包装

后用BufferedReader包

import java.io.*;
public class file4 {
    public static void main(String[] args) throws IOException {
        InputStreamReader N=new InputStreamReader (System.in);
        BufferedReader r=new BufferedReader(N);
        String l=r.readLine();
        System.out.println(l);

    }
}

第二部分 面向对象篇

面对过程与面对对象思想

面对过程

当我们在解决一个问题时,会按照预先设定的想法和步骤,一步一步去实现,在这里每一步具体的 实现中都需要我们自己去亲自实现和操作。

举个例子:自己做->买菜->洗菜->切菜->炒菜->吃

我们的角色是: 执行者

特点:费时间、费精力、结果也不一定完美

面向对象

当我们在解决一个问题时,可以去找具有相对应的功能的事物帮着我们去解决问题,至于这个事物 如何工作,与我们无关,我们只看结果,不关心解决流程。

举个例子:叫外卖->下单->餐馆做饭->骑手送餐->吃

我们的角色是: 指挥者

特点:节省时间,节省精力,结果相对完美

面向过程是面向对象的基础,问题可以自己不解决托给别人解决,别人也可以在再托给别人,但最 终,事情必须要处理掉,一旦处理就是面向过程

面对对象和面对过程的差异
  • 面向对象是一种符合人们思考习惯的思想
  • 面向过程中更多的体现是执行者,面向对象中更多的体现是指挥者。
  • 面向对象可以将复杂的问题进行简单化,更加贴近真实的社会场景

继承

extends

定义

子类可以继承父类的非私有 方法与属性

子类可以调用父类的非私有成员 父类不可以调用子类的成员

兄弟类之间也不可互相调用

super

调用父类属性和方法时候用到的方法

如果不写也默认存在

调用方法时候如果子类有父类也有 优先调用子类的 是为重写

简单事例

Animal 动物类

public class Animal {
    String name;
    int month;
    String species;
    public Animal(String name, int month, String species) {
        this.name = name;
        this.month = month;
        this.species = species;
    }
    public Animal() {
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getMonth() {
        return month;
    }
    public void setMonth(int month) {
        this.month = month;
    }
    public String getSpecies() {
        return species;
    }
    public void setSpecies(String species) {
        this.species = species;
    }
    public void eat(){
        System.out.println(this.name+"在吃");
    }
}

Cat 猫类

public class Cat extends Animal {
    String weigth;
    public Cat() {
    }
    public Cat(String name, int month, String species, String weigth) {
        super(name, month, species);
        this.weigth = weigth;
    }
    public void run(){
        System.out.println("小猫"+this.name+"在跑步");
    }
    public void eat(){
        System.out.println("小猫猫好喜欢吃东西");
    }
}

Dog狗类

public class Dog extends Animal {
    String sex;
    public Dog() {
    }
    public Dog(String name, int month, String species, String sex) {
        super(name, month, species);
        this.sex = sex;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public void sleep(){
        System.out.println("狗狗"+this.name+"在睡觉");
    }
}

Main 测试类

public class Main {


    public static void main(String[] args) {
        Dog dd=new Dog("DA",1,"DD","SS");
        System.out.println(dd.sex);#SS
        Cat cc=new Cat("DA",1,"DD","SS");
        cc.eat();#小猫猫好喜欢吃东西
    }
}
私有

private 本类中访问

public 公开

super 调用父类方法 不可以调用数学

this 调用当前类方法

调用优先级

父类静态 ->子类静态-> 父类代码块-> 父类构造-> 子类代码块-> 子类构造

静态优先 父类优先 属性优先

调用有参方法时候 都会先调用父类无参构造方法

final

final修饰的类不能被继承 但是可以去继承其他类

且被定义值后不能被修改 是为定量

对象被 final修饰后 初始化之后不能再修改

设计模式

单例模式
饿汉模式

访问类时候创建实例对象

调用类默认调用同一个实例对象

用空间换时间

public class Single {
    private static Single sing=new Single();

    public static Single getSing() {
        return sing;
    }
}
public class singtxt {
    public static void main(String[] args) {
        Single a=Single.getSing();
        Single b=Single.getSing();
        System.out.println(a==b);//true
    }
}
Single a=Single.sing;
        Single b=Single.sing;
        System.out.println(a==b);//true
懒汉模式

创建类的时候不去实例化类 当第一次调用的时候实例化类 用时间换空间

public class SingleTwo {
    private static SingleTwo sing;
    private SingleTwo(){

    }
    public static SingleTwo getSing() {
        if (sing == null){
            sing=new SingleTwo();
        }
        return sing;
    }

}
public class singtxt {
    public static void main(String[] args) {
        SingleTwo a=SingleTwo.getSing();
        SingleTwo b=SingleTwo.getSing();
        System.out.println(a==b);
    }
}
工厂模式

介绍

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。

例子

请添加图片描述

代码

package chouxiang;

public class text {//测试类
    public static void main(String[] args) {
        Factory1 factory=new  AppleFactory();//获取工厂
        iPhone phone=factory.createiPhone();//生产手机
        phone.print();//手机
    }
}
interface Factory1{//工厂接口
    iPhone createiPhone();
}
class HuaweiFactory implements Factory1{//华为工厂
    public HuaweiFactory() {
        System.out.println("欢迎来到华为工厂 我可以生产华为手机");
    }
    @Override
    public iPhone createiPhone() {
        return new HuaweiiPhone();
    }
}
class  AppleFactory implements Factory1{// Apple工厂
    public  AppleFactory() {
        System.out.println("欢迎来到 Apple工厂 我可以生产 Apple手机");
    }
    @Override
    public iPhone createiPhone() {
        return new  AppleiPhone();
    }
}
interface iPhone {//手机类接口
    void print();
}
class HuaweiiPhone implements iPhone{//Huawei手机实现
    public HuaweiiPhone() {
        System.out.println("华为手机已经产出 我有  print  输出手机名字功能 ");
    }
    @Override
    public void print() {
        System.out.println("华为手机");
    }
}
class  AppleiPhone implements iPhone{// Apple手机实现

    public  AppleiPhone() {
        System.out.println(" Apple手机已经产出 我有  print  输出手机名字功能 ");
    }

    @Override
    public void print() {
        System.out.println(" Apple手机");
    }
}

结果

欢迎来到 Apple工厂 我可以生产 Apple手机
 Apple手机已经产出 我有  print  输出手机名字功能 
 Apple手机

优缺点

优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。
2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。

抽象工厂模式

介绍

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

例子

请添加图片描述

代码

package chouxiang;

public class text1 {
    public static void main(String[] args) {
        Factory factory =new FactoryB();//类似于向上转型
        Mask mask= factory.createMask();
        mask.method();
    }
}
interface Factory{//工厂类
    public iPhone createiPhone();
    public Mask createMask();
}
class FactoryA implements Factory{
    public FactoryA() {
        System.out.println("欢迎来到 工厂A  我有 createiPhone()  生产华为手机  和 createMask() 生产N95口罩功能  ");
    }
    @Override
    public iPhone createiPhone() {
        return new  HuaweiiPhone();
    }

    @Override
    public Mask createMask() {
        return new N95Mask();
    }
}
class FactoryB implements Factory{
    public FactoryB() {
        System.out.println("欢迎来到 工厂B  我有 createiPhone()  生产 Apple手机  和 createMask() 生产KN90口罩功能  ");
    }
    @Override
    public iPhone createiPhone() {
        return new   AppleiPhone();
    }

    @Override
    public Mask createMask() {
        return new KN90Mask();
    }
}
interface Mask{//口罩类
    void method();
}
class N95Mask implements Mask{
    public N95Mask() {
        System.out.println("N 95口罩已经产出 我有 method   输出口罩功能 ");
    }
    @Override
    public void method() {
        System.out.println("我是N95Mask,我是个口罩");
    }
}
class KN90Mask implements Mask{
    public KN90Mask() {
        System.out.println("KN90口罩已经产出 我有 method 输出口罩功能 ");
    }
    @Override
    public void method() {
        System.out.println("我是KN90Mask,我是一个大口罩");
    }
}

注意 抽象工厂中会有部分调用一工厂的方法
抽象工厂就是工厂方法的升级 如果只有一个工厂 抽象工厂等同于工厂

结果

欢迎来到 工厂B  我有 createiPhone()  生产 Apple手机  和 createMask() 生产KN90口罩功能  
KN90口罩已经产出 我有 method 输出口罩功能 
我是KN90Mask,我是一个大口罩

优缺点

优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

多态

定义

编译时多态 (设计时多态): 方法重载

运行时多态(默认多态):java 调用改方法时根据实例来选择调用哪个方法

注意

静态不能被重写

public class cat extends jiao{
    public void jiao(){
        System.out.println("猫叫");
    }
}
public class dogjiao extends jiao{
    public void jiao(){
        System.out.println("狗叫");
    }
}

public class jiao {
   public   void jiao(){
       System.out.println("叫");
    }
}
public class textjiao {
    public static void main(String[] args) {
        jiao [] ABAB=new jiao[5];
        for (int i = 0; i <5 ; i++) {
            int n=(int)(Math.random()*2);
            switch (n){
               case  0:ABAB[i]=new cat();break;
                case  1:ABAB[i]= new dogjiao();break;
            }
        }
        for (int i = 0; i < 5; i++) {
            ABAB[i].jiao();
        }
    }
}

结果

猫叫
猫叫
狗叫
猫叫
狗叫
抽象类
定义
  1. 被abstract修饰过的类是抽象类
  2. 抽象类无法实例化对象
  3. 被abstract修饰过的方法是抽象方法
  4. 抽象方法不可以有方法体
  5. 父类的抽象方法必须被子类重写
  6. 抽象方法必须在抽象类中但是抽象类中不一定有抽象方法
  7. 抽象方法不能有private 、static、final 等关键字
  8. 若子类不想重写父类的抽象方法,可以将子类改为抽象类
  9. 抽象方法实现后访问权限不能小于父类

内部类

定义

可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类

与之对应的 包含内部类的类叫做外部类

匿名内部类
定义

如果某个类的实例只是用一次,则可以将类的定义与类的创建放到一块完成

或者说在定义类的同时就创建一个类,以这种方法定义的没有名字的类称为匿名内部类

匿名内部类编译储存后名称是 :外部类$数字.class

没有构造方法 但是可以重写方法可以有构造代码块

不能有 public protected abstract static final 等关键字

匿名内部类中不能有静态成员

一个匿名内部类一点是在nwe 的后面,可以实现接口也可以继承父类 但是不可兼得

只能创建匿名内部类的一个实例

例子
public abstract class Person {
    public abstract void read();
}

public class PersonTEXT {
    public void read(Person p) {
        p.read();
    }
    public static void main(String[] args) {
        PersonTEXT pt = new PersonTEXT();
        pt.read(new Person() {
            @Override
            public void read() {
                System.out.println("男人喜欢看java");
            }});
        pt.read(new Person() {
            public void read() {
                System.out.println("女人喜欢看杂志");
            }
        });
        Person a = new Person() {
            public void read() {
                System.out.println("男人喜欢看java");
            }
        };
        pt.read(a);
    }
}

成员内部类
定义

内部类在外部使用时候,无法直接实例化,需要借助外部信息才能访问

内部类的访问权限修饰符任意,但是访问范围会受到影响

内部类可以直接访问外部类的成员属性,如果属性同名 默认调用内部类属性

可以通过 外部类名.this.同名变量 的形式访问外部类的属性

内部类编译后的储存命名格式是:外部类$内部类.class

内部类中包含外部类同名方法时候可以通过 外部类名.this.同名变方法的形式访问外部类的方法

获取内部类方法

1,通过外部类.内部类 名字=new 外部类.new内部类 的方法获取

2,通过 外部类.内部类 名字=new 外部类实例.new内部类 的方法获取

3,,通过方法获取 返回内部类

public class person1 {
    public person2 getperson2(){
        return new person2();
    }
    public class person2 {

    }
}
public  class persontext2 {
    //获取方法一
person1.person2 he= new person1().new  person2();
     //获取方法二
person1 a=new person1();
person1.person2 he1= a.new  person2();
    //获取方法三
person1 b=new person1();
person1.person2 he2= b.getperson2();
}
静态内部类
定义

静态内部类中可以直接访问外部类的静态成员 ,

如果要访问外部类的非静态成员,需要用外部类的对象实例

调用静态内部类方法可以不用实例化

person1.person2 he= new person1().person2();//不用第二个new

注意 :

因为为调用是用的是new说以调用的都是初始化的值

想要避免 可以弄一个实例 去调用同一个实例对象

public class person1 {
    static  int age=0;
    static person1 p=new person1();
    public static class person2 {
            public static void getage(int a){
                p.age=a;
                System.out.println(p.age);
            }
    }
}
public  class persontext2 {
    public static void main(String[] args) {
        person1.person2 he= new person1.person2();
        he.getage(50);
    }
方法内部类
定义

不能写静态成员

方法内部类 一般情况下返回方法内部类中的方法

即使返回实例也用不了

接口

定义

【修饰符】 interface 接口名 extends(父接口)

接口中方法默认为抽象方法 abstract 所以不可以被实现

接口默认public

当类去实现接口的时候,需要重写接口中的所有抽象方法,如果不想重写 将改实现类改为抽象类 abstract

接口中可以包含常量 默认为 public static final

jdk1.8之后 新增的

在接口中 方法前加default 可以带方法体

default修饰后可以重写 默认不出现 方法体为 接口名.super(方法名)

(里面加变量 可以实现漫天过海效果)

方法前加静态 static 也可以 实现方法 但是不可以被重写只能被调用

可以用 接口名.方法名调用

接口与接口同名方法 必须重写 否者调用会报错

或者调用的时候 接口名.成员

接口与继承 同名方法 默认是继承的

接口的父类方法 与接口方法重名 调用为接口方法

接口与实现类 同名 看 调用引用

对比抽象类接口
相同均可以包含抽象方法
都不能被实例化
都是引用数据类型,抽象类的子类或接口的实现类都可以向上转型
不同点一个类只能继承一个抽象类,即单继承一个类可以实现多个接口
抽象类可以包含抽象方法、静态方法、构造方法等,且抽象方法前必须加abstract关键字修饰。接口中可以有抽象方法、默认方法、静态方法。接口中的抽象方法默认为publicabstract,在实际编程中可以省略。接口中的默认方法和静态方法可以包含方法体。
抽象类中可以定义实例属性,也可以定义静态常量属性接口中只能定义静态常量属性,且定义时就初始化

异常

定义

什么是异常

异常就是字面翻译的意外,例外的意思,也就是非正常情况

错误在我们编写程序的过程中会经常发生,包括编译期间和运行期间

编译期间出现的错误有编译器帮助修正 运行时候出现 如 除0

Throwable是所有异常的父类

Exception 所有程序员可处理异常父类

Error 是程序无法处理的异常 在应用程序出现的异常 比如内存溢出

异常有哪些

NullPointerException 空异常

    String str=null;
       System.out.println(str.length());
 

ArrayIndexOutOfBoundsException

越界异常

       int [] ary={1,2,3};
  System.out.println(ary[3]);

ArithmeticException

除数为0 算数异常

           int one=12;
           int twe=0;      System.out.println(one/twe);
代码格式
try {
    //代码1
    //产生异常的代码段2
}catch (异常类型 ex){
    //对异常进行处理的代码段3
}finally {
    //代码4 
    
}

try必须连接0个或多个catch 或者直接连接finally

catch中 不可以出现同种类型

try {
       Scanner in=new Scanner(System.in);
       System.out.println("请输入第一个数字");
       int one=in.nextInt();
       System.out.println("请输入第二个数字");
       int twe= in.nextInt();
       System.out.println(one/twe);
   }catch (ArithmeticException e){
       //打印异常的堆栈信息
      // e.printStackTrace();
       System.out.println("请不要将除数至为0");
   }catch (InputMismatchException e){
       System.out.println("请不要输入字母");
   }
   catch (Exception e){

   }finally {
       System.out.println("finally代码块运行啦");
   }

finally代码块

finally块如果有return 会返回finally中return

即使try块中已经返回了 或者异常中返回了

即使catch中依然二次报错了finally依然会执行

如果try return返回了 finally依然会执行

但是 即使返回值对象在finally中改变了 依然会返回之前没有运行finally时候的缓存

  public static void main(String[] args) {
     System.out.println(trys());
    }
    public static int trys(){
        int i=1;
        try {
            return i;
        }finally {
            System.out.println("finally代码块运行啦");
            i++;
        }
    }

结果

finally代码块运行啦
1
方法

System.exit(0)//终止虚拟机;

System.exit(1);//程序遇到异常终止 大于finally

e.toString()获取的信息包括异常类型和异常详细消息,而e.getMessage()只是获取了异常的详细消息字符串。

throw声明异常

throws抛出异常

public static int trys() throws ArithmeticException {
            return 1/0;
    }

标记文档 效果是使鼠标悬浮时候会显示

/**
 * 如果抛出的是非检查形异常 
 * 可以用文档注释标记异常信息
 * @throws ArithmeticException  
 *
 */
public static void main(String[] args) {
try {
            System.out.println(trys());
    }catch (ArithmeticException e){
        System.out.println("算数异常");
    }catch (Exception e) {
        System.out.println("未知异常");
    }
    }
    public static int trys() throws Exception {
            return 1/0;
    }

结果

算数异常

因为抛出的异常会向上转型 处理时候依然会转回去

自定义异常

首先需要继承父类 Exception

然后构造方法里面 去super父类方法

异常链问题 Exception(“ str内容 ”,e )

如 throw new Exception(“ e.getMessage() ”,e )

throw new 自定义异常名()

ex.initcause(e)携带异常

包装类

定义
基本类型包装类型属于包
intIntegerNumber
charCharacterobj
-****其他都为首字母大写Number包

装箱 基本类型转换为包装类

拆箱 包装类转换为基本类型

int T1=10;
Integer T2=T1;//;自动装箱
Integer T4=new Integer(T1);//手动装箱
int T3=T2;//拆箱
int T5=T4.intValue();//手动拆箱
方法

java.long包下

reverse(int i)

反转数字

paeseInt(String s)

字符串转换为Integer类型

parseInt(String s)

字符串转为Integer类型

Integer.valueOf(obj s)

任意类型转为int类型

        String i="123";
        int o=Integer.valueOf(i);
        System.out.println(o);

int类型转换为字符串

        int n=100;
        String str=""+n;
        Integer n1=n;
        String str2=n1.toString();
        String str3=String.valueOf(n);
Integer比较
  Integer a=new Integer(100);
        Integer b=new Integer(100);
        System.out.println(a==b);//false
        Integer c=100;
        Integer d=100;
        System.out.println(c==d);//true
         c=128;
         d=128;
        System.out.println(c==d);//false
        Integer e=new Integer(100);
        Integer f=100;
        System.out.println(e==f);//false

为什么第二个 和第三个答案不一样

因为-128 到 127 会在缓存池里面留有地址会直接引用

其他值每次使用都会new新的

类型转换
		float f1=88.99F;
        String i=new Float(f1).toString();
        System.out.println(i);
        String J="12.11";
        double K =new Double(J);
        double L =Double.valueOf(J);
        double O =Double.parseDouble(J);
        System.out.println(K);
        System.out.println(J);
        System.out.println(O);
Double C=3;//报错  int不会拆装箱  会默认Integer

这篇 文章我写的时候经常因

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zzsaixuexi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值