Java基础学习
参考资料
参考笔记1:https://www.kuangstudy.com/bbs/1486242169726898178#header23
参考笔记2:https://www.kuangstudy.com/bbs/1464859409422233602#header5
java常识
Java的诞生路线
- C语言接近汇编,很快,很高效,但是并不完全跨平台,而且很容易出错而药等程序运行才能发现。并且操控内存,指针那些比较复杂。所以诞生了C++
- C++的游戏这方面做的很好,但是对比C复杂很多,不易入门。并且还是有一些繁琐。这个时候Java应运而生。
- Java,最开始想叫C++--,就是保留了C++的部分优势,又删掉了一些复杂的东西。后来还是起名叫java了。
Java特性和优势
-
简单性
-
面向对象
-
可移植性
Write Once, Run Anywhere
-
高性能
-
分布式
-
动态性
-
多线程
-
安全性
-
健壮性
Java三大版本
JavaSE:标准版(桌面程序,控制台开发......)
JavaME:嵌入式开发 (手机,小家电....)
JavaEE: E企业级开发(web端,服务器开发...)
JDK,JRE,JVM
JDK: Java Development Kit
- jdk是java开发环境,包括了JRE,而JRE又包括了JVM。而jdk在jre的基础上又加了一些工具
JRE: Java Runtime Environment
- java运行时环境。只要装了jre就可以运行java程序了。而真实情况下安装了JDK就可以了,因为jdk包含jre呀
JVM : JAVA Virtual Machine
- java虚拟机(相当于在所有的系统上装了一个java的cpu)
java开发环境搭建
- 卸载JDK
1.删除Java的安装目录
2.删除JAVA_HOME
3.删除path下关于Java的目录
4.java -version - 安装JDK
1.百度搜索JDK8,找到下载地址
2.同意协议
3.下载电脑对应的版本
4.双击安装JDK
5.记住安装的路径
- 配置环境变量
1.我的电脑-->右键->属性
2.环境变量-->JAVA_HOME
3.配置path变量 - 测试JDK是否安装成功
1.打开cmd
2.java -version
JDK文件夹中的相关文件
(1)bin
存放Javac.exe(Java编译器);Java.exe(Java运行程序);jar.exe(打包工具);Javadoc.exe(文档生成工具)等可执行文件。
(2)db
小型数据库,学习JDBC的时候不需要再安装数据库软件。
(3)include
JDK由于是用C和C++实现的,这里存放了需要引入的C语言的头文件。
(4)jre
Java运行环境目录,包含了JVM(Java虚拟机);运行时的类包;Java启动器以及一个bin目录,但不包括开发环境中的开发工具。
(5)lib
library的缩写,意为Java类库或库文件,是开发工具使用的归档包。
(6)Javafx-src.zip
存放Java FX(Java图形用户界面工具)的源代码。
(7)src.zip
存放JDK的核心源代码。
(8)Javac.exe和Java.exe的区别
①Javac.exe是Java编译器,Java源文件为 .java,此工具将源文件编译为 .class 文件。
②Java.exe负责运行Javac.exe编译后生成的*.class文件。
第一个java程序Hello.java
public class Hello {
public static void main(String[] args) {
System.out.println("hello world");
}
}
Java程序运行机制
- 编译型 -已经解释完成
- 解释型 -边执行边解释
程序运行机制
java基础语法
注释
1)单行注释
//这是单行注释
2)多行注释
/*
* 这是多行注释
* 这是多行注释
* 这是多行注释
* ……
*/
3)JavaDoc文档注释
/** 文档注释 */
关键字
标识符
数据类型
- 知识点
- 例子(long类型一定要加大写L,养成好习惯!小写l容易看成1)
什么是字节?
数据类型扩展
- 整数扩展
进制
二进制0b
十进制
八进制0
十六进制0x
- 浮点数扩展
- 字符扩展
-
转义字符(制表符,换行符)和new 开辟新的地址空间
\r的话就是,将光标定位到当前行首
- 布尔值扩展
这两种是一样的
类型转换
案例
- 强制转换(字符串不能用这种方式强转为int,因为,String不属于基本数据类型,而属于引用数据类型)
- 自动转换
注意点
案例
字符(强制与自动案例)
操作较大数的时候注意溢出问题
JDK7新特性,数字之间可以用下划线分割
变量、常量、作用域
变量
变量作用域
- 实例变量和局部变量
- 类变量(从属于类,不需要创建对象就可以用)
变量的默认值
布尔值为 false
int 为 0
String 为 null
除了基本类型,其余的默认值都是null
当我去掉了,static(报错)
常量
变量的命名规范
运算符
- %为取余,也叫做模运算
- 解释
运算符 | 运算 | 范例 | 结果 | 说明 |
---|---|---|---|---|
+ | 正号 | a=3;+a | 3 | 算数运算符 |
- | 负号 | b=4;-b | -4 | 算数运算符 |
+ | 加 | 5+5 | 10 | 算数运算符 |
- | 减 | 6-4 | 2 | 算数运算符 |
* | 乘 | 3*4 | 12 | 算数运算符 |
/ | 除(整除的结果) | 7/5 | 1 | 算数运算符 |
% | 取模(求余数) | 7%5 | 2 | 算数运算符 |
++ | 自增(前) | a=2;b=++a | a=3;b=3 | 算数运算符 |
++ | 自增(后) | a=2;b=a++ | a=3;b=2 | 算数运算符 |
— | 自减(前) | a=2;b=—a | a=1;b=1 | 算数运算符 |
— | 自减(后) | a-2;b=a— | a=1;b=2 | 算数运算符 |
= | 赋值 | a=2 | 把2赋值给a | 赋值运算符 |
> | 大于 | 关系运算符 | ||
< | 小于 | 关系运算符 | ||
>= | 大于等于 | 关系运算符 | ||
<= | 小于等于 | 关系运算符 | ||
== | 等于 | 关系运算符 | ||
!= | 不等于 | 关系运算符 | ||
&& | 与 | 逻辑运算符 | ||
\ | \ | 或 | 逻辑运算符 | |
! | 非(取反) | 逻辑运算符 | ||
& | 与 | 位运算符 | ||
\ | 或 | 位运算符 | ||
^ | 非(取反) | 位运算符 | ||
~ | 取反 | 位运算符 | ||
>> | 右移 | 将底数/2 | 位运算符 | |
<< | 左移 | 将底数*2 | 位运算符 | |
>>> | 位运算符 | |||
?: | 偷懒 | 条件运算符 | ||
+= | 偷懒 | a=2;b=2; | a+=b;其实是a=a+b | 扩展赋值运算符 |
-= | 偷懒 | a=2;b=2; | a-=b;其实是a=a-b | 扩展赋值运算符 |
*= | 偷懒 | a=2;b=2; | a=b;其实是a=ab | 扩展赋值运算符 |
/= | 偷懒 | a=2;b=2; | a/=b;其实是a=a/b | 扩展赋值运算符 |
算术运算符
赋值运算符
关系运算符
- 小细节
按照容量优先级自动转换
一堆类型,有long的,输出的一定是long
有int的一定是int
这几个double的一定是double
- 关系运算符返回结果
- 扩展赋值运算符
++与--
扩展 :幂运算,(算平方,与次方),这里是3的2次方,等于9
逻辑运算符与短路运算
位运算符
字符串连接符(字符串拼接符)
三元运算符
运算符优先级
包机制
包的本质就是文件夹
.*为通配符
Javadoc生成文档
- 在线的java8 的api帮助文档:https://docs.oracle.com/javase/8/docs/api/
- 自己生成帮助文档
(1)参数
①@author 作者名
②@version 版本号
③@since 指明需要最早使用的JDK版本
④@param 参数名
⑤@return 返回值情况
⑥@throws 异常抛出情况
(2)举例
package com.lovi.base.learn;
/**
* @author Lovi
* @version 1.0
* @since 1.8
*/
public class JavaDoc {
/**
*
* @param a
* @return
* @throws Exception
*/
public String test(String a)throws Exception{
return null;
}
}
生成文档的方法
- 命令行
生成命令:javadoc 参数 **.java
①先到该文件的目录,然后导航栏加上cmd进入doc窗口
②输入javadoc -encoding UTF-8 -charset UTF-8 **.java
③也可以使用IDE来生成,以eclipse和idea为例
过程
双击index.html
生成啦
- idea
Tools→Generate JavaDoc
一不小心把全部都给生成了
zh_CN
-encoding utf-8 -charset utf-8
成功啦,(只打开我要生成的)
- 还可以这样
这样
Java流程控制
用户交互Scanner(输入!!)
例子
- 用next()
package com.lovi.base.learn.scanner;
import java.util.Scanner;
public class Demo1 {
public static void main(String[] args) {
//新建一个scanner对象
Scanner scanner = new Scanner(System.in);
System.out.println("用next()的方式接收字符串...");
//判断用户是否还有输入(如果有就执行if,里边的)
if(scanner.hasNext()){
String str1 = scanner.next();
System.out.println("next()==>"+str1);
}
//IO流的类用完都要关闭,否则会一直占用资源,养成好习惯。
scanner.close();
}
}
发现只输出了hello
- 用nextLine
package com.lovi.base.learn.scanner;
import java.util.Scanner;
public class Demo2 {
public static void main(String[] args) {
//新建一个scanner对象
Scanner scanner2 = new Scanner(System.in);
System.out.println("用nextLine()的方式接收字符串...");
//判断用户是否还有输入(如果有就执行if,里边的)
if(scanner2.hasNextLine()){
String str2 = scanner2.nextLine();
System.out.println("nextLine()==>"+str2);
}
//IO流的类用完都要关闭,否则会一直占用资源,养成好习惯。
scanner2.close();
}
}
探索到知识点
简单的方式
package com.lovi.base.learn.scanner;
import java.util.Scanner;
public class Demo3 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入数据");
String str = scanner.nextLine();
System.out.println("输入的数据为==》"+str);
}
}
用scanner判断整数和小数
package com.lovi.base.learn.scanner;
import java.util.Scanner;
public class Demo4 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int i = 0;
float f = 0.0f;
System.out.println("请输入整数...");
if(scanner.hasNextInt()){
i = scanner.nextInt();
System.out.println("输入的整数为:"+i);
}else {
System.out.println("输入的不是整数!!!");
}
//=================
System.out.println("请输入小数...");
if(scanner.hasNextFloat()){
f = scanner.nextFloat();
System.out.println("输入的小数为:"+f);
}else {
System.out.println("输入的不是小数!!!");
}
scanner.close();
}
}
如果输错
(发现,这种缺点是,这个整数会自动转换成浮点型)
低精度往高精度自动转换
说白了,就是粗往细自动转换!
sanner 计算一堆输入数据的平均值,和总和
package com.lovi.base.learn.scanner;
import java.util.Scanner;
public class Demo5 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入数据,我们会计算出,数据的总和和平均值");
double x = 0;//输入的数据
int m =0;//数据的个数
double sum = 0;//数据的总和
//只要用户有输入就执行这个循环
while (scanner.hasNextDouble()){
x = scanner.nextDouble();
m++;//个数+1
sum = sum + x;//计算总和,把每次的x都给加进去
System.out.println("当前输入了第"+m+"个数据,总和为:"+sum);
}
System.out.println("数据总和为:"+sum);
System.out.println("数据平均值为:"+sum/m);
}
}
顺序结构
选择结构
if 选择结构
- if单选择结构
判断字符串是否相等!==》 字符串a.equals("字符串b");
- if双选择结构
- if多选择结构
- 嵌套的if结构
switch 多选择结构
switch的表达式也可以是字符串
扩展原理
循环结构
while 循环
do...while 循环
- while 与do...while区别
for循环
for的死循环
练习1:计算0到100之间的奇数和偶数的和
练习2:用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个
package com.lovi.base.learn;
public class ForDemo1 {
public static void main(String[] args) {
//用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个
for(int i = 1;i<=1000;i++){
//算出能被5整除的数
if(i%5==0){
//不换行
System.out.print(i+"\t");
}
//每行输出3个
if(i%(5*3)==0){
//换行
System.out.println();
}
//println 输出完会换行
//print 输出完不会换行
}
}
}
练习3:打印九九乘法表
package com.lovi.base.learn;
public class ForDemo2 {
public static void main(String[] args) {
//打印九九乘法表
/*
1.先打印1列
2.打印全部列(把1的部分变成j)
3.去掉重复值(i<=j)
4.调整样式(每个式子不换行,而是退格,然后j每次变化的时候就换一行)
5.把式子里i和j的位置换掉
*/
for(int j=1;j<=9;j++){
for(int i = 1;i<=j;i++){
System.out.print(i+"*"+j+"="+(j*i)+"\t");
}
System.out.println();
}
}
}
for循环与数组
package com.lovi.base.learn;
public class ForDemo3 {
public static void main(String[] args) {
//数组与for循环
int[] numbers = {1,2,3,4,5};//定义数组
for(int i=0;i<numbers.length;i++){
System.out.println(numbers[i]);
}
//重点
System.out.println("=====================");
for(int x:numbers){
//原理,把numbers的每个数组的元素都赋值给x,然后逐个输出
System.out.println(x);
}
}
}
continue 与break与goto
(goto,不建议使用,了解即可)
练习
打印三角形
package com.lovi.base.learn;
public class ForDemo4 {
public static void main(String[] args) {
//打印三角形
/*
思路,先打印一半的三角形(空格)再打印一半的三角形实体
再复制一份实体
*/
for(int i=0;i<=5;i++){
for(int j=5;j>i;j--){
System.out.print(' ');
}
//反过来打三角形
for(int j1=0;j1<=i;j1++){
System.out.print('*');
}
//再复制一份(去掉顶角)
for(int j1=0;j1<i;j1++){
System.out.print('*');
}
System.out.println();
}
}
}
关键点是把空格也看成是打印的部分
java方法详解
何谓方法
方法的定义及调用
方法定义
形式参数与实际参数
在方法里,return还有一个作用是终止方法
方法调用
记住
方法重载
实例
命令行传参
用main方法传递参数
可变参数
必须放在最后一个参数
可变参数,本质是数组
package com.lovi.base.learn.method;
public class Demo1 {
public static void main(String[] args) {
//可变的参数
new Demo1().happy(1,2,3,6,5,434532,32);
}
public void happy(int... numbers){
for (int i=0;i<numbers.length;i++){
System.out.println("numbers["+i+"]"+"==>>"+numbers[i]);
}
}
}
递归
- 原理
深度大的时候不适合用递归,会占用大量的空间内存,导致电脑卡住。
能不用递归尽量不用递归。
递归主要是思想的学习。递归思想。递归只适合小基数的运算。
- 例子
package com.lovi.base.learn.method;
public class Demo2 {
public static void main(String[] args) {
//用递归计算阶乘
//5!=5*4*3*2*1;
System.out.println(new Demo2().factorial(5));//计算5的阶乘并输出,得到120
}
public int factorial(int num){
//设置边界
if(num==1){
return 1;
}else {
//不符合边界就往边界调用。5*4...
return num*factorial(num-1);
}
}
}
练习
package com.lovi.base.learn.method;
import java.util.Scanner;
public class Demo3 {
public static void main(String[] args) {
/*
写一个计算器,要求实现加减乘除功能,并且能够循环接收新的数据,通过用户交互实现。
思路推荐:
写4个方法:加减乘除
利用循环+switch进行用户交互
传递需要操作的两个数
输出结果
*/
double a = 0;
double b = 0;
String c = "a";
int d =1;//作为循环判断
Scanner scanner = new Scanner(System.in);
while (d==1){
System.out.println("《===========游戏开始==============》");
System.out.println("请输入第一个数");
a = scanner.nextDouble();
System.out.println("请输入+或者-或者*或者/");
c =scanner.next();
System.out.println("请输入第二个数");
b = scanner.nextDouble();
//创造对象
Demo3 demo3 = new Demo3();
switch (c){
case "+":
demo3.add(a,b);
break;
case "-":
demo3.subtract(a,b);
break;
case "*":
demo3.multiplication(a,b);
break;
case "/":
demo3.division(a,b);
break;
default:
System.out.println("输入不合法!!");
}
System.out.println("输入1继续游戏,输入0,退出游戏");
d= scanner.nextInt();
}
scanner.close();
}
//加减乘除四个方法
public void add(double a ,double b){
System.out.println(a+"+"+b+"="+(a+b));
}
public void subtract(double a ,double b){
System.out.println(a+"-"+b+"="+(a-b));
}
public void multiplication(double a ,double b){
System.out.println(a+"*"+b+"="+(a*b));
}
public void division(double a ,double b){
System.out.println(a+"/"+b+"="+(a/b));
}
}
运行结果
《===========游戏开始==============》
请输入第一个数
10
请输入+或者-或者*或者/
+
请输入第二个数
10
10.0+10.0=20.0
输入1继续游戏,输入0,退出游戏
1
《===========游戏开始==============》
请输入第一个数
10
请输入+或者-或者*或者/
-
请输入第二个数
10
10.0-10.0=0.0
输入1继续游戏,输入0,退出游戏
1
《===========游戏开始==============》
请输入第一个数
10
请输入+或者-或者*或者/
*
请输入第二个数
10
10.0*10.0=100.0
输入1继续游戏,输入0,退出游戏
1
《===========游戏开始==============》
请输入第一个数
10
请输入+或者-或者*或者/
/
请输入第二个数
10
10.0/10.0=1.0
输入1继续游戏,输入0,退出游戏
0
Process finished with exit code 0
java数组
数组定义
数组声明创建
原理
数组的四个基本特点
package com.lovi.base.learn.array;
public class Demo1 {
public static void main(String[] args) {
//数组的声明与创建
int[] nums;//声明
nums = new int[10];//创建 (开辟空间)
//初始化,让其为1,2,...10
for(int i=0; i<nums.length;i++){
nums[i]=i+1;
}
//输出
for(int x:nums){
System.out.println(x);
}
}
}
输出:
三种初始化以及内存分析
内存分析
如果我不去赋值的话,它就会走默认初始化
三种初始化
默认初始化其实就是默认值!
数组边界和小结
数组使用
- for-each
- 数组作方法入参
- 数组作方法入参
反转数组
二维数组
二维数组
数组的数组
(原理)
原理:
例子
package com.lovi.base.learn.array;
public class Demo2 {
public static void main(String[] args) {
//二维数组的理解与应用
int[][] nums = {{1,2},{3,4},{5,6},{7,8}};
//输出一下
System.out.println(nums[0]);//打印出来的是对象
//用取出每一个值的方法打印才行
printArray(nums[0]);
System.out.println("取出每个数据");
System.out.println(nums[0][1]);
}
//打印数组元素
public static void printArray(int[] arrays){
for (int i = 0; i < arrays.length; i++) {
System.out.print(arrays[i]+" ");
}
System.out.println();
}
}
Arrays类讲解
实例
package com.lovi.base.learn.array;
import java.util.Arrays;
public class Demo3 {
public static void main(String[] args) {
//Array类的几个妙用,说白了它是个工具类,里边有很多方法可以用,就很方便
int[] nums = {1, 3, 2, 32, 432, 11, 23, 43, 34};
//数组输出
System.out.println(nums);//就只是对象
System.out.println(Arrays.toString(nums));
//数组排序
Arrays.sort(nums);
System.out.println(Arrays.toString(nums));
//数组填充(在下标2,和4之间填充6,(不包括4))
Arrays.fill(nums,2,4,6);
System.out.println(Arrays.toString(nums));
}
}
排序
一共有八大排序
参考教程:https://blog.csdn.net/m0_63111921/article/details/123796971
一,选择排序-直接插入排序(Direct insertion sort)
- 元素集合越接近有序,直接插入排序算法的时间效率越高
2.时间复杂度:O(n^2)(情况最差时,即逆序转有序,最好为O(n));
3.空间复杂度:O(1);
4.稳定
package com.lovi.base.sort;
import java.util.Arrays;
public class Demo01 {
//插入排序(从小到大排列)
public int[] InsertSort(int[] a){
//要插入的轮数
for (int i = 0; i < a.length-1; i++) {
int temp = a[i+1];//要插入数数据
int end=i;//要比较的值的下标
//end>=0保证往前每个都比较
while (end>=0){
//保证从小到大。
// 如果要插入的数据比前面的小,原本temp占用的位置空出来,给前面的退后。
if (temp < a[end]){
a[end+1]=a[end];//原本前面的退后
end--;//比较的值的往前移动(下标-1)
}else {
break;
}
a[end+1]=temp;
}
}
return a;
}
public static void main(String[] args) {
int a[] = {8, 7, 6, 5, 4, 3, 2, 1};
int b[] = {1,4,2,8,2,4,1,3,2};
new Demo01().InsertSort(a);
System.out.println(Arrays.toString(a));//结果:[1, 2, 3, 4, 5, 6, 7, 8]
}
}
二,插入排序-希尔排序(Shell sort)
- 希尔排序是对直接插入排序的优化。
- 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
- 希尔排序的时间复杂度不好计算,需要进行推导,推导出来平均时间复杂度: O(N1.3—N2)
- 稳定性:不稳定
package com.lovi.base.sort;
import java.util.Arrays;
public class Demo02 {
//希尔排序(从小到大排列)
public int[] ShellSort(int[] a){
int gap = a.length;
while(gap>1)//判断是否还需排序
{
gap=(gap/3+1);//保证最后一次直接插入排序
for(int i=0;i<a.length-gap;i++)//进入循环,对每一组进行排序
{
int end=i;
int tmp=a[end+gap];
while(end>=0)
{
if(tmp<a[end])
{
a[end+gap]=a[end];
end-=gap;
}
else
{
break;
}
a[end+gap]=tmp;
}
}
}
return a;
}
public static void main(String[] args) {
int a[] = {8, 7, 6, 5, 4, 3, 2, 1};
new Demo02().ShellSort(a);
System.out.println(Arrays.toString(a));//结果:[1, 2, 3, 4, 5, 6, 7, 8]
}
}
三,选择排序-简单选择排序(Simple selection sort)
1,容易理解,但是效率太低,实际当中不太使用
2,时间复杂度O(n^2),空间复杂度O(1);
3,不稳定
package com.lovi.base.sort;
import java.util.Arrays;
public class Demo03 {
//希尔排序(从小到大排列)
public int[] selectSort(int[] a) {
int left = 0;
while (left < a.length) {
int min = left;
for (int i = left; i < a.length; i++)//找最小值
{
if (a[min] > a[i]) {
min = i;
}
}
//交换数据 然后找次小,交换
int temp = a[left];
a[left] = a[min];
a[min] = temp;
left++;
}
return a;
}
public static void main(String[] args) {
int a[] = {8, 7, 6, 5, 4, 3, 2, 1};
new Demo03().selectSort(a);
System.out.println(Arrays.toString(a));//结果:[1, 2, 3, 4, 5, 6, 7, 8]
}
}
冒泡排序
时间复杂度为O(n2)
package com.lovi.base.sort;
import java.util.Arrays;
public class Demo05 {
//冒泡排序
public int[] bubbleSort(int[] a){
//外层循环,冒泡排序的轮数
for (int i = 0; i < a.length-1; i++) {
//内层循环,每轮交换的次数
for (int j = 0; j < a.length-1-i; j++) {
//开始交换,从小到大排,小的在前面,若发现大的在前面就换
if(a[j]>a[j+1]){
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
return a;
}
public static void main(String[] args) {
int a[] = {8, 7, 6, 5, 4, 3, 2, 1};
new Demo05().bubbleSort(a);
System.out.println(Arrays.toString(a));//结果:[1, 2, 3, 4, 5, 6, 7, 8]
}
}
四,选择排序-堆排序(Heap sort)
。。。。
稀疏数组
例子
- 解答
package com.lovi.base.learn.array;
public class Demo5 {
public static void main(String[] args) {
//稀疏数组,了解即可
//1.打印出原来的数组
int[][] a1 = new int[11][11];
a1[1][2]=1;
a1[2][3]=2;
System.out.println("原数组");
//打印数组
for (int i = 0; i < a1.length; i++) {
for (int j = 0; j < a1.length; j++) {
System.out.print(a1[i][j]+"\t");
}
System.out.println();
}
//2.打印出稀疏数组
//先算出有效数字才知道多少行!
int sum=0;//有效数字
for (int i = 0; i < a1.length; i++) {
for (int j = 0; j < a1.length; j++) {
if(a1[i][j]!=0){
sum++;
}
}
}
System.out.println("有效数字==》"+sum);
int[][] a2 = new int[sum+1][3];
//行 列 值
a2[0][0]=11;
a2[0][1]=11;
a2[0][2]=sum;
//遍历二维原数组,将非0的值放入稀疏数组中
int count=0;//计数器
for (int i = 1; i < a1.length; i++) {
for (int j = 0; j < a1.length; j++) {
if(a1[i][j]!=0){
count++;
a2[count][0]=i;
a2[count][1]=j;
a2[count][2]=a1[i][j];
}
}
}
System.out.println("稀疏数组");
//打印数组
for (int i = 0; i < a2.length; i++) {
for (int j = 0; j < a2.length; j++) {
System.out.print(a2[i][j]+"\t");
}
System.out.println();
}
//3.打印出稀疏数组还原的数组
int[][] a3 = new int[a2[0][0]][a2[0][1]];
//给有效值赋值
for (int i = 1; i < a2.length; i++) {
a3[a2[i][0]][a2[i][1]] = a2[i][2];
}
System.out.println("还原后的稀疏数组");
//打印数组
for (int i = 0; i < a3.length; i++) {
for (int j = 0; j < a3.length; j++) {
System.out.print(a3[i][j]+"\t");
}
System.out.println();
}
}
}
结果
原数组
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
有效数字==》2
稀疏数组
11 11 2
1 2 1
2 3 2
还原后的稀疏数组
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
Process finished with exit code 0
面向对象编程
初识面向对象
面向过程 & 面向对象
方法回顾和加深
方法的调用
结论:同类型的方法可以互相调用!
原理:
形参和实参(值传递)
引用传递
对象的创建分析
类和对象的关系
- 类与对象关系探索
实例
代码
Student
package com.lovi.base.learn.oop.demo1;
public class Student {
//属性
String name;
int age;
//方法
public void study(){
System.out.println("学生在学习!");
}
}
Application
package com.lovi.base.learn.oop.demo1;
public class Application {
public static void main(String[] args) {
//一个项目应该只有一个启动类!
/*
类:抽象的,可以被实例化
类实例化之后会返回一个对象
student1和student2都是对象
student对象就是Student类的一个具体的实例
*/
Student student1 = new Student();
Student student2 = new Student();
String xiaoMing = student1.name = "小明";
student1.age = 18;
student2.name = "小红";
student2.age = 6;
//输出属性
System.out.println(xiaoMing);
System.out.println(student1.age);
System.out.println(student2.name);
System.out.println(student2.age);
//方法调用!
student1.study();
}
}
构造器详解
例子
关键点
/*
构造器:
1. 和类名相同
作用:
2. 没有返回值
1. new 本质在调用构造方法
注意点:
2. 初始化对象的值
1. 定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造
Alt + Insert
this. =
*/
代码
Person
package com.lovi.base.learn.oop.demo1;
public class Person {
String name;
int age;
String gender;
//构造器(这是隐含的)
public Person(){
}
//有参数
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
}
Application
package com.lovi.base.learn.oop.demo1;
public class Application {
public static void main(String[] args) {
//测试person
//无参
Person person = new Person();
person.name = "小白";
System.out.println(person.name);
System.out.println("==========");
person = new Person("小红");
System.out.println(person.name);
System.out.println("==========");
person = new Person("小黄",19);
System.out.println(person.name+"\t"+person.age);
System.out.println("==========");
person = new Person("小绿",20,"女");
System.out.println(person.name+"\t"+person.age+"\t"+person.gender);
}
}
结果
创建对象内存分析
例子
new的时候
赋值的时候
类与对象小结
1. 类与对象
类是一个模板:抽象,对象是一个具体的实例
2. 方法
定义、调用!
3. 对象的引用
引用类型: 基本类型(8)
对象是通过引用来操作的:栈--->堆
4.属性:字段Field成员变量
默认初始化:
数字:0 0.0
char: u0000
boolean: false
引用:null
修饰符 属性类型 属性名 = 属性值!
5. 对象的创建和使用
- 必须使用new 关键字创造对象,构造器 Person kuangshen = new Person();
- 对象的属性 kuangshen.name
- 对象的方法 kuangshen.sleep()
6. 类:
静态的属性 属性
动态的行为 方法
面向对象三大特性:封装,继承,多态
封装
属性私有,get、set
封装的作用
提高程序的安全性,保护数据
隐藏代码的实现细节
统一接口
系统可维护增加了
- 实例
属性私有爆红
Person
package com.lovi.base.learn.oop.demo1;
public class Person {
//属性私有,封装起来
private String name;
private int age;
//get/set方法(public)给外界提供接口
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age>120||age<0){
System.out.println("年龄不合法,系统自动判定为三岁小孩");
this.age = 3;
}else {
this.age = age;
}
}
}
Application
package com.lovi.base.learn.oop.demo1;
public class Application {
public static void main(String[] args) {
//测试封装
Person person = new Person();
person.setName("小明");
System.out.println(person.getName());//小明
person.setAge(999);//年龄不合法,系统自动判定为三岁小孩
System.out.println(person.getAge());//3
}
}
继承
快捷键 ctrl+h 可以看到继承关系
定义了final的类不能被继承,没有子类,断子绝孙!
父类(基类)
派生类,子类
子类继承了父类,就会拥有父类的全部方法!
私有的东西无法被继承
实例
- super
对于属性
对于方法
对于构造器
默认先执行父类的构造方法,再执行子类的,所以,子类的构造方法隐含了super();
super注意点:
1. super调用父类的构造方法,必须在构造方法的第一个
2. super 必须只能出现在子类的方法或者构造方法中!
3. super和 this 不能同时调用构造方法!
Vs this:
代表的对象不同:
this: 本身调用者这个对象
前提
super: 代表父类对象的引用
this:没有继承也可以使用
构造方法
super:只能在继承条件才可以使用
this();本类的构造
super():父类的构造!
- 方法的重写
这是静态方法
方法的调用只和左边,定义的数据类型有关
父类的引用指向了子类
重写都是方法的重写,和属性无关
这是非静态方法
发现方法重写只和非静态方法有关
重写注意点
重写:需要有继承关系,子类重写父类的方法!
1. 方法名必须相同
2. 参数列表列表必须相同
3. 修饰符:范围可以扩大但不能缩小: public>Protected>Default>private
4. 抛出的异常:范围,可以被缩小,但不能扩大; ClassNotFoundException --> Exception(大)
重写,子类的方法和父类必要一致;方法体不同!
为什么需要重写:
1. 父类的功能,子类不一定需要,或者不一定满足
Alt + Insert; override;
多态
多态学习关键点:
父类型,可以指向子类,但是不能调用子类独有的方法
左边(Student):能调用的方法都是自己的或者继承父类的!Student s1 = new Student();
对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
子类重写了父类的方法,执行子类的方法
多态注意事项:
1. 多态是方法的多态,属性没有多态
2. 父类和子类,有联系 类型转换异常! ClassCastException!
3. 存在条件: 继承关系,方法需要重写,父类引用指向子类对象!Father f1 = new Son();
不能重写的方法:
1. static 方法,属于类,它不属于实例
2. final 常量;
3. private方法;
instanceof和类型转换
instanceof 关键,如果匹配,可以进行类型之间的转换
看有没有父子关系
static关键字
静态属性
静态方法
package com.lovi.base.learn.oop.demo1;
public class Teacher extends Person{
//static关键字
//静态方法
public static void teach(){
System.out.println("教书");
}
//非静态方法
private void happy(){
System.out.println("开心");
}
public static void main(String[] args) {
Teacher.teach();
System.out.println("==========");
new Teacher().happy();
}
}
代码块
package com.lovi.base.learn.oop.demo1;
public class Teacher extends Person{
//static关键字
{
//匿名代码块,在对象创建时就有了
System.out.println("匿名代码块!");
}
static {
//静态代码块
System.out.println("静态代码块");//只执行一次
}
public Teacher(){
System.out.println("构造方法!");
}
//静态属性
private static String name;
private int age = 18;
public static void main(String[] args) {
new Teacher();
System.out.println("==========");
new Teacher();
}
}
//静态导入包
package com.lovi.base.learn.oop.demo1;
import static java.lang.Math.PI;
import static java.lang.Math.random;
import static java.lang.Math.*;//通配符直接导入整个Math
public class Teacher extends Person{
//static关键字
//静态导入包
public static void main(String[] args) {
System.out.println("随机方法"+Math.random());
System.out.println("静态导入包"+PI);
System.out.println("静态导入包"+random());
//Math.floor(18.1);
System.out.println("向下取整"+floor(18.9999));
}
}
抽象类和接口
抽象类
//子类必须重写抽象类的所有抽象方法 除非它自己也是抽象类
抽象类存在构造器,子类可以用super调用
接口
接口中定义的变量,其实都是常量(一般都不会这么做)
接口作用:
1. 约束
2.定义一些方法,让不同的人实现~ 10
3. public abstract (接口中的方法)
4. public static final (接口中的属性)
5,接口不能被实例化~,接口中没有构造方法~
6. implements可以实现多个接口
7,必须要重写接口中的方法~
内部类及OOP实战
方法里也能写内部类,称之为局部内部类
没有名字的内部类(匿名内部类)
异常机制
Error和Exception
捕获和抛出异常
实例
异常处理
知识:
快捷键:选中想要处理异常的语句,然后ctrl+alt+t(选择)
主动抛出异常与方法上抛出(处理不了)
自定义异常及经验小结
实例
测试
代码
package com.lovi.base.learn.exception;
//自定义异常
public class A extends Exception {
//传递的数字大于10则抛出异常
private int a;
public A(int a) {
this.a = a;
}
//打印异常信息
@Override
public String toString() {
return "我的自定义异常{" +
"异常=" + a +
'}';
}
}
package com.lovi.base.learn.exception;
public class Test {
//可能存在异常的方法(抛出我的自定义异常)
public void test(int a)throws A{
if(a>10){
throw new A(a);//主动抛出异常
}
System.out.println("OK");
}
public static void main(String[] args) {
try {
new Test().test(12);
} catch (A e) {
System.out.println("测试异常捕获==》"+e);
} finally {
}
}
}
异常处理小贴士