一.hello World!
-
新建一个文件夹,存放代码
-
建一个java文件
-
文件后缀为.java
-
文件名为Hello.java
-
系统可能没有显示文件后缀名,需手动打开。文件系统菜单栏查看-选✓文件扩展名。
-
-
编写代码,注意class名和文件名一致。
-
编译javac Hello.java文件,会生成一个class文件,在文件路径前输cmd空格回车即可进入cmd窗口(并指向当前java所在的地址下)。在cmd窗口上方右键选择属性打开字体,可调节字体大小。
-
运行java Hello无后缀class,默认允行class文件。
注意点:
- 每个单词得大小不能出现问题,java是大小写敏感的。
- 输出或使用英文。
- 文件名和类名必须一致,并且首字母大写。
- 符号使用了中文。
二.java程序运行机制
高级语言特性
- 编译型(compile):编译器,一次翻译全部,翻译为计算机识别的语言
- 解释型:实时翻译,有一些性能损失
区别:java两个都有,先预编译为class,运行时机不同,源文件改变编译型要在全部翻译代价较大。
编译型:已经编译好,只执行编译后的文件就行,执行效率快,速度快,对操作系统平台要求低,操作系统的开发语言,C/C++
解释型:网页,服务器脚本语言,实时解释,速度慢。
三.JVM执行过程
class:源文件到机器码之间的文件—虚拟机类加载器(jvm)—字节码校验器(代码对否)—解释器(读取class解释给操作系统)—操作系统平台。
程序:将一系列的指令按规定的流程执行。
四. 注释、标识符、关键字
- 单行注释
- 多行注释
- 文档注释:JavaDoc
/**
* JavaDoc
* @Author xxx
* @Description xxx
* JavaDoc
*/
有趣的代码注释:“佛祖”
- 所有标识符都以字母(A-Z或者a-z),美元符($),或者下划线(_)开始
- 首字母之后可以是字母(A-Z或者a-z),美元符($),或者下划线(_)或数字的任何字符的组合
- 不能以关键字作为变量名或方法名
- 标识符是大小写敏感的
-
强类型语言:要求变量的使用要严格符合规定,所有变量定义后才能使用
变量定义后使用过程中一直维持变量类型,安全性高但速度差
-
弱类型语言:
-
静态修饰符的特点:
- static是一个修饰符,用于修饰成员(成员变量和成员函数)
- 静态成员随着类的加载而加载。
- 静态成员优先于对象存在。
- 静态成员被所有对象所共享
- 静态成员多了一个中调用方式,可以被类名直接调用。
- 静态修饰的数据对象共享的数据,存放在方法区的静态区中。
非静态的数据,是每一个对象特有数据。存放在对象的所属的堆内存中。
- 静态使用的注意事项——多线程中使用
- 静态方法只能访问静态成员, 非静态方法既可以访问静态又可以访问非静态。
- 静态方法中不可以定义this,super关键字。因为this代表是对象。而静态存在时,有可能没有对象。所以静态方法运行时,this是没有任何对象代表的。
- 简单说,先进内存的数据不可以访问后进内存的数据,可是后进内存数据可以访问先进内存的数据。
- 主函数是静态的
- 静态的优缺点
- 优点: 静态成员多了一种调用方式。可以直接被类名调用 格式 :类名.静态成员。也可以被对象调用。
- 弊端 : 静态方法只能访问静态成员,出现了访问局限性。
- 当成员变量被静态修饰后,和非静态成员变量的区别:
- 静态变量也称为类变量,也就是直接可以被类名调用的变量。这个变量是所属于类的。
非静态变量成为成员变量,或者实例变量,是被对象调用的,是所属具体对象的。 - 静态变量随着类的加载而加载,也意味着随着类的消失而消失。生命周期最长。
实例变量,随着对象的创建而加载,随着对象的消失而消失。按照对象的生命周期而存在。 - 静态变量存储在方法区的静态区中。
实例变量存在于对象所属的堆内存中。 - 静态变量数据,被所有对象所共享。
实例变量是对象中的特有数据 - 静态代码块:类加载,只执行一次。首先执行
static{
//静态代码块
}
- 非静态代码块:匿名代码块,对象创建时加载。第二执行(赋初始值)
{
//匿名代码块
}
- 构造函数第三执行。
- 静态倒入包:
import static java.lang.Math.random;
System.out.println(random());
-
类要想被其他包导入,必须声明为public。被public修饰的类,类名必须与文件名相同。
-
访问修饰符\作用范围 所在类 同一包内其他类 其他包内子类 其他包内非子类 private 可以访问 不可以 不可以 不可以 缺省 可以 可以 不可以 不可以 protected 可以 可以 可以 不可以 public 可以 可以 可以 可以
五.数据类型
- 基本类型:
- 数值类型:
- 整数类型
- byte占1个字节:-128·128
- short占2个字节:-32768·32768
- int占4个字节:正负21亿
- long占8个字节+L
- 浮点类型(float占4个字节)+F
- double占8个字节
- 字符类型char:占2个字节
- boolean类型:占1位只有true和false
- 引用类型:
- 类:String是类不是关键字
- 接口
- 数组
- 位(bit):是计算机内部存储数据的最小单位,11111001是一个8b二进制数
- 字节(byte):计算机处理数据的基本单位,用B表示
- 1B = 8b
- 电脑32位和64位区别:寻址能力不同32位只能用32为系统,最多支持4G内存,64可以支持32、64位系统,最多支持128G内存
- 字符:计算机中使用字母、数字、字和符号char 一个字符
六.类型转换(基本数据类型的范围看其对应的引用类型)
- 整数拓展—进制:二进制:0b 八进制:0 16进制:0x (0-9 A-F 15)开头
- 浮点数拓展:银行业务如何拓展
- float : 表现子长有限、除法下来是无限的、离散的、舍入误差、大约但不等于
- double
- 避免浮点数的比较
- BigDecimal 数学工具类
- 字符拓展:所有的字符本质还是数字
char c1 = 'a';
char c2 = '中';
System.out.println(c1);
System.out.println((int)c1);
//强制转换
System.out.println(c2);
System.out.println((int)c2);
//强制转换
a
97
中
20013
- 编码 Unicode 表:(97=a 65=A) 占2字节 0 -65536 excel表格长度 2 16=65536
- U0000-Uffff
char c3 = '\u0061';
System.out.println(c3);
a
- 转义字符
- \t 制表符
- \n 换行
- …
- 字符串:对象从内存分析
String sa = new String("hello world!");
String sb = new String("hello world!");
System.out.println(sa == sb);
String sc = "hello world!";
String sd = "hello world!";
System.out.println(sc == sd);
false
true
- 布尔值拓展
boolean flag = true;
if(flag == true){} //新手
if(flag){} //老手
//less is more 代码要精简已读
- 类型转换:强类型语言,运算是需要类型转换
byte,short,char—>int—>long—>float—>double(低到高)(小数优先于整数)
- 运算中,不同类型的数据先转换为同一类型,然后在进行运算。
int i = 128;
byte b = (byte)i; //内存溢出
//强制转换
System.out.println(b);
-128(不确定变为多少)
- 强制转换:高—>低
- 自动转换:低—>高
- 不能对布尔值进行转换
- 不能把对象类型转换为不相关的类型
- 转换存在内存溢出,精度问题
(int)23.7 //23
(int)45.231f //45
char i = ‘a’; //97
int b = i+1; //98
char c = (char)b //b
- 操作比较大的数,注意内存溢出问题
//JDK7新特性,数字之间可以用下划线分割
int k = 10_0000_0000;
System.out.println(k);
1000000000
- long L(用此) l(不用,容易和1搞混)
七.变量、常量
- 强类型语言,每个变量必须声明类型,直指内存中的空间(位置确定,内容不定)
- 变量是程序中基本的存储单元,三要素:变量名(合法标识符),变量类型(基本类型、引用类型),作用域;
- 变量声明是完整语句,每个声明必须一分号结尾
- 程序的可读性;多个变量不要声明在一行,一个变量一行。
- 变量作用域
- 类变量(类里面,有static)—类属性从属于类,和类一同出现和消失,在方法中可以(sout)直接输出。
- 实例变量(类里面,无static)—类属性,从属于对象
变量类型(自定义类型,引用类型)
变量名 值
class cname = new classname();
cname.xx
cname.xx
- 局部变量(类方法里面,必须声明和初始化值。作用域:方法里面)
- 方法块:代码块:作用域整个类空间中
static{
}
static{作用域整个类空间中}
- 实例变量不自行初始化,就赋值这个类型的默认值
- 数值类型默认是0(整数)、0.0(小数)
- 字符型默认值为’\u0000’,二进制16b上都为0的Unicode,即空值,也是0
- 布尔值:默认为false
- 非基本类型其他默认值为null
6.常量:特殊的变量,初始化后无法改变。(提高可读性、静态常量、直接引用)
- final double PI = 3.14
- final 常量名 = 常量值
- 常量名用大写字母
- public 、static、final都是修饰符不区分前后位置
八.变量命名规范
- 所有的变量、方法、类名:见名知意
- 类成员变量:首字母小写和驼峰原则
- 局部变量:首字母小写和驼峰原则
- 常量:大写字母和下划线:(单词较多时加下划线)MAX_VALUE
- 类名:首字母大写和驼峰原则
- 方法名:首字母小写run()和驼峰原则runRun()
九.运算符
- 算数运算符:% 模运算*(取余)、++、–
int a = 10;
int b = 20;
int c = 30;
System.out.println(a/b);
System.out.println(a/(double)b);
0
0.5
除法除到小数来注意精度范围
long a = 123456789L;
int b = 123;
short c = 10;
byte d = 7;
System.out.println(a+b+c+d);
System.out.println(b+c+d);
System.out.println(c+d);
123456929
140
17
有Long类型的运算结果是Long类型,有Double类型的运算结果是Double类型,同时有Long、Double类型时Double,没有 Long、Double类型都是int类型,无论是不是有int类型参与
- 关系运算符:>=、<=、==、!=、instanceof
- (自增)++、–(自减)一元运算符
int a = 3;
int b = a++; //执行完这句代码后,先赋值,后自增
//a = a + 1;
System.out.println(a);
//a = a + 1;
int c = ++a; //执行完这句代码后,先自增,后赋值
System.out.println(a);
System.out.println(b);
System.out.println(c);
4
5
3
5
//幂运算 2^3 java中无^ 用工具类来操作 System.out.println(Math.pow(2,3));
- 短路运算 段路与
//短路运算 短路与
int m = 5;
boolean n = (m<5)&&(m++)<8;
System.out.println(n);
System.out.println(m);
false
5
- 位运算
/*
a = 0011 1100
b = 0000 1101
a&b = 0000 1100 (同一为一)
a|b = 0011 1101 (有一为一)
a^b = 0011 0001 (同数为0,异数为1)异或
~b = 1111 0010
*/
/*
2*8 = 16 最快的算法 2*2*2*2
<< 位左移 *2 >>位右移 /2 效率极高
0000 0000 0
0000 0001 1
0000 0010 2
0000 0011 3
0000 0100 4
0000 1000 8
0001 0000 16
*/
- 字符串连接符 +
int a = 10;
int b = 20;
//字符串连接符 + String在后面,前面先运算,在+拼接、String在前面面,直接+拼接
System.out.println(a+b+"");
System.out.println(""+a+b);
- 优先级:()>一元运算符>二元运算符>按位与或非
十.包机制、JavaDoc
- 包的本质是文件夹:防止命名空间重复问题。
- 利用公司域名倒置作为包名:www.baidu.com ==>com.baidu.www
- 倒包import 置在 package下方
- 倒包时注意包里面的文件、类名字不要重复。
- JavaDoc命令用来生成自己的API文档的,参数信息
- @author
- @version
- @since指明最早使用的jdk版本
- @param参数名
- @return
- @throws 异常抛出情况
- javadoc -encoding UTF-8 -charset UTF-8(中文乱码) xxx.java
十一.人机交互、循环结构
- Scanner对象,Java5提供的新特性,获取用户的输入:
- 可以不加判断条件,直接接受输出
//从键盘接受数据
Scanner scanner = new Scanner(System.in);
System.out.println("使用next方式接收");
//判断用户有没有输入字符串
if (scanner.hasNext()){
String nextStr = scanner.next(); //程序等待用户输入完毕才停止运行
System.out.println("用户输入字符是:"+nextStr);
}
//凡事属于I/O流的类如果不关闭会一直占用资源,好习惯
scanner.close();
hello world!
hello
//从键盘接受数据
Scanner scanner = new Scanner(System.in);
System.out.println("使用nextLine方式接收");
//判断用户有没有输入字符串
if (scanner.hasNextLine()){
String nextLineStr = scanner.nextLine();
System.out.println("用户输入下一行:"+nextLineStr);
}
//凡事属于I/O流的类如果不关闭会一直占用资源,好习惯
scanner.close();
hello world!
hello world!
- next()和nextLine()区别:
- next()以空格作为结束符,nextLine()以enter以回车作为结束符
- next()不能得到空白字符,nextLine()可以
- 一定要输入有效字符后才可以结束输入
- 顺序结构:java的基本结构就是顺序结构,是最简单的算法结构。是任何一个算法都离不开的一种基本算法结构。
- 选择结构:
- if单选择结构:
- if双选择结构:
- if多选择结构:
- 嵌套的if结构:
- switch多选择结构:变量与一系列值是否相等,每个值都称为一个分支
switch(expression) {
case value:
break; //可选
case value:
break;
default: //可选
- switch语句中变量可以是:
- byte,short,int或者char;
- 从javase7开始支持String;字符的本质还是数字,字符、串的hashcode()值
- 反编译-字节码文件–反编译idea
- 同时case标签必须为字符串常量或字面量。
- **不写break;则会出现case穿透(匹配项后面的几项都输出) **
- 循环结构:顺序结构程序只执行一次,所以需要循环结构。
- java5中引入了一种主要用于数组的增强型for循环
while(布尔表达式){
//循环内容
}
- while直到布尔表达式为true,循环就会一直下去
- 大多数情况是会让循环停止下来,需要一个表达式失效的方式来结束循环。
- 少部分会一直循环下去,入服务器的请求响应监听。
- 循环条件一直为true就会造成无限循环(死循环)
- do…while循环:对于while语句而言,不满足条件不进入循环。但有时即使不满足条件也至少执行一次。
- do…while循环和while相似,不同点do…while至少循环一次。
- For循环:执行次数是在执行前就确定了。循环里面a+=2 //叫迭代
- 是支持迭代的之中通用结构,是最有效,最灵活的循环结构。
- 最先执行初始化不在,可以声明一种类型,但可初始化一个或多个循环口感那只变量,也可以是空语句
for(;;){}
- 增强for循环,java5引入,主要用于数组和集合的增强型for循环。
for(声明语句 : 表达式){
}
- 声明语句:声明新的局部变量,该变量的类型必须和数组元素类型匹配。作用域限定在循环语句块,其值与此时数组元素的值相等。
- break和continue:break在任何循环语句主体部分均可实现控制循环的流程,强行退出循环。
- goto关键字:java保留字,并未得到正式使用,java没有goto,可用带标签的break和continue实现
- 标签:后面跟一个冒号的标识符,如:label;
- java唯一用到标签的地方是在循环语句之前。在循环之前设置标签的唯一理由是:嵌套另一个循环,让break和continue随标签使用,会中断到标签的地方
- 质数:大于1的自然数中,除了1和它本身外不再有其他因数的自然数。
//输出101到150之间的质数
//跳出循环到标签所在处
outer:for (int i = 101; i <= 150; i++) {
for (int j = 2; j < i/2; j++) {
if(i%j==0){
continue outer;
}
}
System.out.print(i +"\t");
}
//打印三角形
//先打印倒三角:占位
//再打印一半的正三角:反向操作
//最后打印另一半的正三角:拼接
for (int i = 1; i <= 6; i++) {
//倒三角:占位
for (int j = 6; 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();
}
- 方法:保持方法的原子性,一个方法只完成1个功能,这样利用后期发展
-
System.out.println(); 类 System类中包含PrintStream类out对象println()是PrintStream类的方法
-
形参和实参、static functionName()转换为类方法可通过类.functionName()调用。
-
方法包含与类和对象中,在程序中创建在其他地方调用
-
main()方法简洁干净,其他公共方法抽取出来进行调用,被JVM调用
-
return:终止方法,程序需要严谨,对程序负责
-
值传递还是引用传递:java都是值传递(拷贝的概念)
- 方法的重载:一个类中,相同的函数名称,但形参不同的函数(实现理论:方法名称相同时编译器会根据调用方法的参数个数、参数类型进行逐个匹配,选择对应的方法,匹配失败,编译器报错)
- 方法名称必须相同
- 参数类别必须不同(个数、类型、顺序)
- 返回类型可以相同或不同
- 返回类型不同不足以成为方法的重载
- 命令行传递参数:cmd给main方法传递参数
- args.length 数组长度
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lqVy1gx4-1647339792536)(C:\Users\CNCLUKZK\AppData\Roaming\Typora\typora-user-images\image-20220309235636784.png)]
package com.zk.operator; //路径问题
--需退回到src目录下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-32pWkpla-1647339792538)(C:\Users\CNCLUKZK\AppData\Roaming\Typora\typora-user-images\image-20220310000013849.png)]
- 结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SnioXHg7-1647339792538)(C:\Users\CNCLUKZK\AppData\Roaming\Typora\typora-user-images\image-20220310000453482.png)]
- 可变参数:(本质是数组)命令行参数=不定项参数java1.5开始支持传递同类型的可变参数
- 在方法声明中,在指定的参数类型后加一个省略号(…)
- 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通参数必须在它之前声明。
void test(int... ints){
if(ints.length>0){
for (int m:ints) {
System.out.print(m+"\t");
}
}else {
System.out.println("请传递参数!");
return;
}
}
- 递归:自己掉自己。简单程序解决复杂问题。把大型复杂问题层层转化为一个与原问题相似的规模较小的问题来求解。用有限的语句来定义对象无限集合。exp:阶乘 5! 5+4+3+2+1 + =>乘
-
能不用就不用,用也是基数较小的时候
-
递归结构两部分:递归头,什么时候不调用自身方法,如果没有头将陷入死循环。==边界条件
-
递归体:什么时候需要调用自身方法。前阶段: 返回阶段n*(n-1)
-
会死循环,即栈溢出
-
缺点:嵌套层次深的算法不适用勒,物理上内存崩溃。深度越深,时空性越差。
public long mult(long m){
if(m == 1){ //边界
return 1;
}else {
return m * mult(m - 1); //循环体
}
}
- java使用栈机制。先入后出,main方法在最底层,main里调用一方法,栈加一层。main执行完,栈清空。
- 数组:相同类型数据的有序集合,大小定义后就不可改变。
- 相同类型的若干数据,按一定的先后次序组合而成;
- 其中每个数据称为一个数组元素,通过下标来访问。从0开始
- 数组的声明与创建:
- 数组声明才能使用;1.java方式 2.c/c++方式
dataType[] arrayRefVar; //首选
dataType arrayRefVar[]; //次选效果相同
- 创建:new 创建
dataType[] arrayRefVar = new dataType[arraySize];
- 通过length属性定义长度
- 里面元素没赋值则用默认值:int=0,String=null
十二.数组的四个基本特点:
- 长度确定,一旦被创建,其大小无法改变
- 元素必须是相同类型,不允许出现混合类型
- 数组元素可以是任何数据类型,包含基本和引用类型
- 数组变量是引用类型,数组可作为对象,数组中的每个元素相当于该对象的成员变量。数组本身是对象,存在堆中,所以数组无论保存原始,类型还是其他对象类型,本身存在与堆中的。
- 数组初始化:
- 静态初始化:创建并复制:int[] array = {x,x,x,x} //还有引用类型类数组 类[] array = {new XXX(),new XXX(),new XXX()}
- 动态初始化:new int[size]之后再赋值
- 默认初始化:数组是引用类型,他的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也按照实例变量类型隐式赋给其初始值。
- java内存:
- 堆:存放new的对象和数组;可被所有线程共享,不会存放别的对象引用;
- 栈:存放基本变量类型(包含这个基本类型的具体数值);引用对象的变量(存放这个引用在堆里面的具体地址)
- 方法区:可被所有线程共享;包含所有的chass和static变量
- 数组声明变量在栈中,此时数组并不存在,new创建对象后在内存堆中开辟空间
- 数组的使用:普通for循环做其他操作
- 增强型for循环:打印结果
//JDK1.5后使用,没有下标
for (int a:array ) {
System.out.println(a);
}
- 作为方法参数(for循环格式)和返回值
//数组反转
public static int[] reverse(int[] array){
int[] result = new int[array.length];
for (int i = 0,j = array.length-1;i<array.length;i++,j--){
result[j] = array[i];
}
return result;
}
- 多维数组:数组的数组,二维数组中每个元素都是一维数组。
- int[] [] a =new [2] [5] //可看成2行五列的数组
int[][] array = {{1,3},{4,5},{5,6},{7,8},{8,9}};
- 多维数组=面向对象
- Arrays类: 数组的工具类java.util.Arrays。数组本身没有什么方法可以供我们调用,API中提供了此类进行调用,
- Arrays类中的方法都是用static修饰的静态方法,使用的时候可以直接使用类名进行调用,不用非不能
- 常用功能:1.给数组赋值,通过fill方法,即给数组各元素填充值;2.对数组排序,通过sort方法来升序;3.比较数组,通过equals方法比较数组中元素值是否相等。4.通过binarySearch方法对排序好的数组进行二分法查找
//自定义数组输出方法,同Arrays.toString(arr),避免重复造轮子
static void sortArrays(int[] arr){
for (int i = 0; i < arr.length; i++) {
if(i == 0){
System.out.print("[");
}
if(i == arr.length-1){ //自定义处理数组元素和","
System.out.println(arr[i] + "]");
}else {
System.out.print(arr[i] +", ");
}
}
}
- 排序算法:8种以上、冒泡排序
- 冒泡代码,两层循环,外层冒泡轮数,里层依次比较。嵌套循环,算法的时间复杂度为O(n2)
/*
* 外层轮数
* 内层这一轮两两比较,最大,最小数*/
static int[] sortArray(int[] arr){
int temp;
boolean flag = false;
//外层轮数,arr.length-1轮防止数组越界
for (int i = 0; i < arr.length-1; i++) {
//比较过的就不在比了
for (int j = 0; j < arr.length-1-i; j++) {
if(arr[j+1] < arr[j]){
temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
flag = true;
}
}
//优化思路,最后一轮不比较了
if(!flag){
break;
}
}
return arr;
}
- 数据压缩算法:稀疏数组,数据结构的一种
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wYycreJF-1647339792539)(E:\zkNote\2.语言学习\java\稀疏数组.png)]
- 记录原始数组横纵行列数、即有效值总个数/记录有效坐标、记录原始数值,
public static void main(String[] args) {
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 2;
//System.out.println("输入原始数组:");
//printArray(array1);
System.out.println("原始数组array1有效值个数:");
int sum = 0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if(array1[i][j]!=0){
sum++;
}
}
}
System.out.println("原始数组array1有效值个数:"+sum);
creatArray(array1,sum);
}
/**
* 打印二维数组元素
* @param array
*/
static void printArray(int[][] array){
for (int[] ints:array) {
for (int intValue:ints) {
System.out.print(intValue+"\t");
}
System.out.println();
}
}
//创建一个稀疏数组
/**
*
* @param array 原始数组
* @param sum 原始数组有效值个数
*/
static void creatArray(int[][] array,int sum){
int[][] array2 = new int[sum+1][3]; //有效值个数+1第一行数组信息
array2[0][0] = 11;
array2[0][1] = 11;
array2[0][2] = sum;
int count = 0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if(array[i][j]!=0){
count++;
array2[count][0] = i;
array2[count][1] = j;
array2[count][2] = array[i][j];
}
}
}
printArray(array2);
//还原稀疏数组
int[][] array3 = new int[array2[0][0]][array2[0][1]];
for (int i = 1; i < array2.length; i++) {
//for (int j = 0; j < array2[i].length; j++) { //无用
array3[array2[i][0]][array2[i][1]] = array2[i][2];
//}
}
System.out.println("还原稀疏数组");
printArray(array3);
}
十三.面向对象编程OOP
- 面向对象(Object-Oriented Programming):属性+方法=类
-
本质:以类的方式组织代码,以对象的形式组织(封装)数据
-
抽象:像==类似点
-
类:静态的属性+动态的方法
-
面向过程:步步做什么;适合处理简单的问题;线性思维;
-
面向过程:物以类聚,分类抽象概念,先抽想,在细化;复杂问题,多人协作;
-
对于复杂事物,从宏观上把握,整体合理性分析,面向对象分 的思路处理具体问题。
-
认识论:现有对象后又类。对象,具体的事物,类,对对象共同点进行抽象。
-
代码实现:现有类后又对象
- 方法回顾
-
方法无返回值时void return;结束方法,或返回一个结果
-
静态方法(static):
-
非静态方法:
//和类一起加载的static,无法调用不存在的方法
public static void a(){
//b();
}
//类实例化之后才存在
public void b(){
}
- 异常:在方法参数后,throws exception
- 实际参数和形式参数的类型一一对应
- 值传递(java)(值拷贝、被调用处不影响原来的数据)和引用传递(传对象的引用地址、本质还是值传递)内存概念
- 一个类里面只有一个public class可以有多个class
- this关键字:代表当前这个类或对象
- 对象创建:对象通过引用来创建栈–>堆(地址)
- 类是一种抽象的数据类型,对一类事物的整体描述,不能代表具体的事物
- 对象是对抽象概念的具体实例
- new关键字创建时,除了分配内存空间之外,还给创建好的对象进行默认的初始化以及对类中构造器的调用
- 构造器=构造方法:创建对象是必须调用,特点:1.必须和类名相同;2.必须没有返回值,也不能写void
- 属性=成员变量
- 默认构造器实例化初始值
- 数字:0、0.0 char:u0000 boolean:false 引用:null
String name;
//实例化初始值
public Student(){
this.name = "zk";
}
- 使用new关键字,必须要有构造器()本质调用
- 有参构造:一旦定义有参构造,必须显示定义无参构造,否则其子类无法调用super()无参,只能调用父类有参构造器
- main()方法存在内存中的栈中[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xegIHACj-1647339792539)(E:\zkNote\2.语言学习\java\java对象创建内存.png)]
- 面向对象3大特性
- 封装(对于类的属性而言):高内聚,低耦合。高内聚,类的内部数据操作细节自己完成,不许外部干涉。低耦合:暴露少量方法给外边使用。
- 封装:数据的隐藏,禁止直接访问对象中数据的实际,而通过操作接口来访问,这是信息隐藏
- 属性私有,get/set
- 在set方法中做安全性检查,避免破坏系统
public void setAge(int age) {
if(age>120||age<0){
this.age = 3;
}else {
this.age = age;
}
}
- 意义:a.提高程序的安全性,保护数据
- b.隐藏代码的细节
- c.统一接口
- d.系统的可维护性
- 继承:本质是对某一批类的抽象,从而实现对现实世界更好的建模
- extends是”扩展“子类对父类的扩展
- java是单继承,非多继承,直接继承一个,间接多个
- 继承是类与类之间的一种关系。还有依赖,组合(类中有其他类),聚合
- 子类(派生类)父类(基类)子类继承父类用extends表示
- java中,所有的类默认直接或间接继承Object这个父类
public native int hashCode();
- super:父、this当前的 super.xxx super.xxx()父类属性和方法,必须在构造方法的第一个
- super只能出现在子类的方法和构造器中
- super()和this()不能同时调用构造方法。都必须放构造器第一行。
public Student() {
super(); //子类无参构造默认加这句,调用父类的无参构造器,必须放在子类构造器的第一行
System.out.println("student无参构造!");
}
- 私有的内容无法被继承
- vs this
- 代表的对象不同:this本身调用这这个对象;super父类对象的引用
- 前提:this没有继承也可以用super只能在继承条件下使用
- 构造方法:this():本类的构造super父类的构造
- 重写:是对public方法的重写,和属性无关,跟非静态方法有关,与静态方法无关。前提:前提存在继承关系,子类重写父类方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s0Zb52tw-1647339792540)(E:\zkNote\2.语言学习\java\重写和静态方法关系.png)]
- 重写和非静态方法关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Df1LtDR0-1647339792540)(E:\zkNote\2.语言学习\java\重写和非静态方法关系.png)]
-
静态方法是类方法,非静态方法是成员方法,依赖于对象,对象中方法重写则调用就不同,即子类重写了父类的方法
-
方法的调用只和左边定义的数据类型有关
方法名必须相同 |
---|
参数列表必须相同,方法体不同 |
修饰符范围可以扩大不能缩小public>protected>default>private |
抛出的异常:范围可缩小,不可被扩大:ClassNotFoundexception->Exception1 |
- 意义:父类的方法子类不一定需要
-
多态:动态编译。程序的这个类型在执行时确定,代码不限制死,大型系统可以扩展:同一方法根据发送对象的不同而采用不同的行为方式;对象的实际类型确定,但指向对象的引用可以多种类型(父类、有关系的类)
-
存在条件:1.有继承关系
-
2.子类重写父类方法
-
3.父类的引用(类型)可以指向子类实例(但不能调用子类独有的方法)
-
同名方法子父类都有,默认就重写;子父类各自有自己的方法,父类(引用类型)不可用子类的方法
-
一个对象的实际类型是确定的(new),但可以指向的引用类型就不确定了–变量名
-
注意点: 无法重写的方法 多态;对于方法而言的,属性没有方法 static:类方法,不属于实例 有联系的类,否则转换异常(ClassCastException) final:常量 继承关系,方法被重写,父类引用指向子类对象 private:方法
- instanceof:判断引用变量类型和别的类是否存在父子关系 :instanceof比较的实例对象的实际类型
- 引用类型间(类型转换):
- 父转子:要强转,从而调用子类独有方法,即父类引用指向子类对象
- 子转父:直接转。会丢失子类独有的方法。
- 方便方法的调用,减少代码的重复
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yKPcRCjw-1647339792540)(E:\zkNote\2.语言学习\java\多态间的关系运行.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CESB3zr4-1647339792541)(E:\zkNote\2.语言学习\java\多态间的关系运行结果.png)]
- 抽象类和接口
- abstract修饰方法和类,修饰方法为抽象方法(只有方法名字,没有实现方法),修饰类为抽象类。
- 必须依靠extends,还是单继承有局限性;
- 抽象类可以没有抽象方法,有抽象方法的一定要声明为抽象类
- 抽象类,不能用new关键字创建对象,用子类创建
- 子类继承抽象类就必须实现抽象类中没有实现的抽象方法,否则子类也声明为抽象类
- 抽象类存在构造器,节省开发效率
- 接口(interface):多继承:就是规范,定义的规则,无法实现方法(约束和实现分离:面向接口编程)
- 没有构造器,不能被实现
- 实现必须重写接口中的方法
- 借口中方法默认都是public abstract
- 接口中的属性都是常量:默认修饰符为public static final (少些)
- 定义方法,让不同人实现
- 内部类:类内部定义类,内部类、外部类
- 成员内部类
public class Outer {
private int id = 10;
public void run(){
System.out.println("外部类方法!");
}
//获得外部类的私有属性,私有方法
public class Inner{
public void run(){
System.out.println("内部类方法!");
}
public void getId(){
System.out.println(id);
}
}
}
public static void main(String[] args) {
Outer outer = new Outer();
//创建内部类对象,通过外部类
Outer.Inner inner = outer.new Inner();
inner.run();
inner.getId();
}
- 静态内部类
//获得外部类的私有属性,私有方法
public static class Inner{
public void run(){
System.out.println("内部类方法!");
}
public void getId(){
//System.out.println(id); 静态区拿不到对象ID
}
}
- 局部内部类:方法中定义类
public class Outer02 {
void run(){
System.out.println("外部类方法");
}
void test(){
//局部变量
//局部内部类
class Outer3{
void testOuter3(){
System.out.println("testOuter3=====局部内部类");
}
}
}
}
- 匿名内部类://没有名字初始化类,不用将实例保存到变量中
//没有名字初始化类,不用将实例保存到变量中
new Outer02().run();
TestService testService = new TestService() {
@Override
public void run() {
System.out.println("匿名内部类的高级操作");
}
};
//一个类文件中可以有多了类,但只能有一个类被public修饰
public class Outer02 {
void run(){
System.out.println("外部类方法");
}
}
//可以临时写测试方法
class Outer1{
public static void main(String[] args) {
Outer02 outer02 = new Outer02();
outer02.run();
}
}
十四.异常机制Exception
- error(无法预料)和exception(可预料)
- 检查性异常:用户错误或问题引起的异常,程序员无法预见。编译时不能被简单的忽略-测试岗
- 运行时异常:运行时异常是可能被程序员避免的异常。跟检查性异常相反,运行时异常在编译时被忽略。
- 错误(error):不是异常,脱离程序员控制的问题,在代码中常被忽略。栈溢出错误。AWTError(GUI编程)
- 错误(error)类对象有java虚拟机生成并抛出,大多数和程序员执行的操作无关;比较致命,程序无法控制和处理,程序终止。
- 异常体系结构
- java把异常挡对象处理,并定义一个基类java.lang.Throwable作为又有异常的超类,可被程序处理。
- 异常类分为两大类错误和异常
- java虚拟机运行错误:jvm不再有继续执行操作所需的内存资源,出现内存溢出错误。发生错误时jvm会终止线程结束程序。
- 虚拟机执行应用时,一些不可查的错误定义错误(NoClassDefFoundError)链接错误(LinkageError)这些错误不可查,在应用程序控制之外,程序运行时不允许出现。
- 运行时异常,非检查性异常可以选择捕获处理也可以不处理,有程序逻辑错误引起,应该要避免。
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y1GdOuE8-1647339792541)(E:\zkNote\2.语言学习\java\Throwable.png)]
- java异常处理机制
-
抛出异常
-
捕获异常
-
try、catch(解决异常的代码写道这里)、finally、throw、throws(方法抛异常) 快捷键Ctrl+Alt+T
-
catch()可以写多个catch()异常,异常范围类型从小到大
-
System.exit(0); //结束程序
-
int a = 1; int b = 0; if(b==0){ throw new ArithmeticException(); }
-
代码中非方法中用throw抛异常,作用不大
-
throw作用在方法体内,throws作用在方法定义上,外部调用方法时调用方都要捕获异常try、catch、finally
- 自定义异常
-
内置异常:java内置异常可以描述大部分异常情况。自定义异常秩序基础Exception类即可。
-
程序中使用自定义异常:
-
创建自定义异常类
-
在方法中通过throw关键字抛出异常对象
-
要么在当前抛出异常方法出处理异常,可以用try、catch捕获并处理;要么在方法声明处通过throws关键字指明要抛出的异常给调用者,让调用者捕获并处理异常。
-
public class MyException extends Exception{ String detail; public MyException(String message, String detail) { super(message); this.detail = detail; } @Override public String toString() { return "MyException{" + "detail='" + detail + '\'' + '}'; } }
public static void main(String[] args) {
try {
test(20);
} catch (MyException e) {
System.out.println(e);
//e.printStackTrace();
}
}
static void test(int a) throws MyException {
if(a > 10){
throw new MyException("异常信息",String.valueOf(a));
}
}
下一篇:java语法-01-java语法进阶
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/123981.html