一、Java数组
1.数组的声明、创建、初始化
数组是相同类型数据的有序集合,按照一定先后次序排列组合而成并可通过下标来访问每个数据。
//数组类型 数组名字 =数组的值
//1.声明一个数组
int[] nums; //首选
int nums2[];//c和c++常用
//2.创建一个数组
nums=new int[10];//可以存放10个数据类型为int的数组
//或者直接结合1和2写成
int[] nums=new int[10];
//3.给数组元素赋值
nums[0]=1; //下标从0开始
nums[1]=2;
nums[2]=3;
nums[3]=4;
nums[4]=5;
nums[5]=6;
nums[6]=7;
nums[7]=8;
nums[8]=9;
nums[9]=10;
//4.获取数组长度
nums.length
2.三种初始化及内存分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZMN8no6C-1620655010053)(C:\Users\zhengxu\AppData\Roaming\Typora\typora-user-images\image-20210510090850450.png)]
三种初始化:
//1.静态初始化:创建+赋值
int[] a={1,2,3}; //定义之后不可改变
Man[] mans={new Man(1,1),new Man(2,2)};
//2.动态初始化:包含默认初始化
int[] b=new int[10];//默认元素为0
b[0]=10;//手动赋值
//3.数组的默认初始化
//数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化
3. 下标越界及小结
数组的四个基本特点:
1.长度确定。一经创建,不可更改。
2.数组元素类型必须相同。
3.数组元素的数据类型可以是任何数据类型,包括基本类型和引用类型。
4.数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。
数组对象本身也在堆中。
数组边界:
下标的合法区间:[0,length-1],如果越界就会报错;
ArrayIndexOutOfBoundsException:数组的下标越界异常!
4.数组的使用
//1.For Each循环
package com.study.ArrayDemo01;
public class Demo01 {
public static void main(String[] args) {
int[] arrays={1,2,3,4,5};
//打印全部的数组元素
for (int x:arrays) {
System.out.println(x);
}
}
}
//2.普通for循环
//打印数组元素
public static void printArrays(int[] arrays){
for(int i=0;i<arrays.length;i+=){
System.out.println(arrays[i]);
}
//3.数组做方法入参,数组作返回值
//反转数组
public static int[] reverse(int[] arrays){
int[] result=new int[arrays.length];
for(int i=0,j=result.length;i<arrays.length;i++,j--){
result[j]=arrays[i];
}
return result;
}
5.二维数组
int[][] a=new int[2][3];//定义了一个两行三列的数组
int[][] b={{1,2,3},{4,5,6}};
a.length//数组所有元素的个数
a[0].length //数组每行元素的个数
a.length/a[0].length //数组每列元素的个数
6.Arrarys类讲解
数组的工具类:java.util.Arrays
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而不用使用对象来调用。
查看JDK帮助文档
package com.study.ArrayDemo01;
import java.util.Arrays;
public class Demo02 {
public static void main(String[] args) {
int[] a={1,2,3,4,5,6,7,8,9,10};
System.out.println(a);//[@45617c 输出了数组的地址
//给数组赋值:通过fill方法
int[] b=new int[3];
Arrays.fill(b, 1,2,3);
//打印数组元素:通过toString方法
System.out.println(Arrays.toString(a));
//对数组排序:通过sort方法
Arrays.sort(a);
System.out.println(Arrays.toString(a));
//比较数组:通过equals方法
System.out.println(Arrays.equals(a,b));
//查找数组元素:通过binarySearch方法
System.out.println(Arrays.binarySearch(a,3));//会返回元素下标
}
}
7.冒泡排序
冒泡排序无疑是最为出名的排序算法之一,总共有八大排序算法!
时间复杂度O(n2)
package com.study.ArrayDemo01;
import java.util.Arrays;
public class Demo03 {
public static void main(String[] args) {
int[] a={1,7,8,3,5,9,5,6,4};
System.out.println("排序前的数组为:"+ Arrays.toString(a));
int[] b=sort(a);
System.out.println("排序后的数组为:"+Arrays.toString(b));
}
//冒泡排序
//1.比较数组中,两个相邻的元素,如果第一个数比第二个大,我们就交换它们的位置
//2.每次比较,都会产生出一个最大,或者最小的数字
//3.下一轮则可少一次排序
//4.依次循环,直到结束
public static int[] sort(int[] array){
int temp=0;
//外层循环,判断需要走多少次;
for (int i = 0; i < array.length-1; i++) {
boolean flag=false;//通过flag标识位减少没有意义的比较
//内层循环,如果第一个数比第二个数大,则交换位置
for (int j = 0; j < array.length-1-i; j++) {
if(array[j+1]>array[j]){
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
flag=ture;
}
}
if(flag==false){
break; //flag没有改变说明第一次排序没有发生位置交换,数组本身就已经排好了, break退出循环
}
}
return array;
}
}
8.稀疏数组
当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方式为:
记录数组一共有几行几列,有多少个不同值
把具有不同值的元素和 行列及值记录在一个小规模的数组中,从而缩小程序的规模
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zoI7j9Bh-1620655010056)(C:\Users\zhengxu\AppData\Roaming\Typora\typora-user-images\image-20210510114656176.png)]
package com.study.ArrayDemo01;
import java.util.Arrays;
public class Demo04 {
public static void main(String[] args) {
//1.创建一个二维数组11*11, 0:没有棋子;1:黑棋;2:白棋
int[][] array1=new int[11][11];
array1[1][2]=1;
array1[2][3]=2;
//输出原始数组
System.out.println("输出原始的数组:");
for(int[] ints:array1){
for(int anInt:ints){
System.out.print(anInt+"\t");
}
System.out.println();
}
//转换为稀疏数组保存
//获取有效值个数
int sum=0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if(array1[i][j]!=0){
sum++;
}
}
}
System.out.println("有效值的个数:"+sum);
//2.创建一个稀疏数组
int[][] array2=new int[sum+1][3];
array2[0][0]=11;
array2[0][1]=11;
array2[0][2]=sum;
//遍历二维数组,将非0的值存放到稀疏数组中
int count=0;
for (int i = 0; i < array1.length; i++) {
for(int j=0;j<array1[i].length;j++){
if(array1[i][j]!=0){
count++;
array2[count][0]=i;
array2[count][1]=j;
array2[count][2]=array1[i][j];//保存横纵坐标和值
}
}
}
//输出稀疏数组
System.out.println("稀疏数组:");
for (int i = 0; i < array2.length; i++) {
System.out.println(array2[i][0]+"\t"+array2[i][1]+"\t"+array2[i][2]);
}
System.out.println("======================");
System.out.println("还原:");
//1.读取稀疏数组
int[][] array3=new int[array2[0][0]][array2[0][1]];
//2.给其中的元素还原它的值
for(int i=1;i<array2.length;i++){
array3[array2[i][0]][array2[i][1]]=array2[i][2];
}
//3.打印
System.out.println("输出还原的数组:");
for(int[] ints:array3){
for(int anInt:ints){
System.out.print(anInt+"\t");
}
System.out.println();
}
}
}
二、面向对象
1.什么是面向对象?
面向过程思想:
步骤清晰简单,第一步做什么,第二步做什么
面对过程适合处理一些较为简单的问题
面向对象思想:
物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后才对某个分类下的细节进行面向过程的思索。
面向对象适合处理复杂的问题,适合处理需要多人协作的问题。
宏观层面适合面向对象思考,微观层面适合面向过程思考。
面向对象编程(Object-Oriented Programming,OPP)
面向对象编程的本质:以类的方式组织代码,以对象的形式(封装)数据。
从代码运行角度分析,先有类后有对象。类是对象的模板。
抽象
三大特性:
封装
继承
多态
2.回顾方法的定义和调用
方法的定义
package com.study.opp;
public class Demo01 {
//main方法
public static void main(String[] args) {
}
/*方法的定义:
修饰符 返回值类型 方法名(参数){
//方法体
return 返回值;
}
*/
public String sayHello(){
return "hello world!";
System.out.println("hello");//return后面不会再运行,是无效代码!!!!
}
}
方法的调用
关键词:static
//假设写了一个学生类Student,采用静态方法,如下:
package com.study.opp;
public class Student {
//静态方法
public static void say(){
System.out.println("hello world!");
}
}
//其它类可以直接调用它,采用类名调用,Student.say()
package com.study.opp;
public class Demo02 {
public static void main(String[] args) {
//静态方法
Student.say();
}
}
//假设是非静态方法:public void say(){}
//则需要在其它类中实例化这个类才能调用
Student student=new Student();
student.say();
//在同一类中的方法调用,静态不能调用非静态,非静态可以调用静态方法
package com.study.opp;
public class Demo02 {
public static void main(String[] args) {
//和类一起加载的
public static void a(){
b();
}
//类实例化之后才存在,因此会报错
public void b(){
}
}
}
值传递和引用传递的区别
package com.study.opp;
//值传递
public class Demo02 {
public static void main(String[] args) {
int a=1;
System.out.println(a);//输出1
Demo02.change(a);
System.out.println(a);//输出1,因为change并没有返回值
}
public static void change(int a){
a=10;
}
}
/*===============================================*/
package com.study.opp;
//引用传递:对象,本质还是值传递
public class Demo03 {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);//null
Demo03.change(person);
System.out.println(person.name);//郑旭
}
public static void change(Person person){
//person是一个对象:指向的是一个具体的人,因此可以改变属性
person.name="郑旭";
}
}
//定义了一个person类,有一个属性name
class Person{
String name;
}
3.类与对象的创建
类是一种抽象的数据类型,它是对某一类十五整体描述定义,但不能代表某一特定事物。
对象是抽象概念的具体实例。
例如:植物是一个类,百合花和洋甘菊是两个对象
创建对象:new
//1.先创建一个学生类
package com.study.opp;
//学生类
public class Student {
//属性:字段
String name;
int age;
//方法
public void study(){
System.out.println(this.name+"在学习");
}
}
//2.实例化类
package com.study.opp;
//一个项目应该只有一个main方法
public class Demo04 {
public static void main(String[] args) {
//类:抽象的,实例化
//类实例化之后会返回一个自己的对象!
//student对象就是一个Student类的具体实例
Student xiaoMing = new Student();
Student xiaoHong = new Student();
//给对象赋值
xiaoMing.name="小明";
xiaoMing.age=12;
xiaoHong.name="小红";
xiaoHong.age=17;
System.out.println(xiaoMing.name+":"+xiaoMing.age+"岁"); //小明:12岁
System.out.println(xiaoHong.name+":"+xiaoHong.age+"岁"); //小红:17岁
}
}
4.构造器详解*
类中的构造器也成为构造方法,是在进行创建对象的时候必须要调用的。
构造器有以下两个特点:
1.必须和类的名字相同
2.必须没有返回类型,也不能写void
作用:
1.new本质在调用构造方法
2.初始化对象的值
注意点:
1.定义了有参构造后,如果想使用无参构造器,必须显式定义一个无参构造!
2.快捷键alt+insert,默认生成有参,选择no可以无参构造
package com.study.opp;
//java————>class
public class Demo05{
//一个类即使什么都不写,也会产生一个方法
}
//在out里面可以看到.class文件,里面是:
package com.study.opp;
public class Demo05 {
public Demo05() { //没有返回类型,名字与类相同
}
}
//=========================================
//显式的定义构造器
package com.study.opp;
//java————>class
public class Person01 {
//一个类即使什么都不写,也会产生一个方法
//显式的定义构造器
String name;
//实例化初始值
//1.使用new关键字,本质是在调用构造器
public Person01(){
}
//有参构造:一旦定义了有参构造,无参必须显式定义!!!!!!!!!
public Person(String name){
this.name=name;
}
}
//其他类调用它时相当于初始化了name的值,如下所示调用有参构造实例化一个对象
Person person=new Person("郑旭");