Java基础学习笔记(狂神说版)
三、Java方法
(一)方法的重载
1. 重载的概念:
重载就是在一个类中,有相同的函数名称,形参不同的函数。
2. 方法重载的规则:
(1)方法名必须相同
(2)参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)
(3)方法的返回类型可以相同,也可以不同
(4)仅仅返回类型不同不足以成为方法的重载
3. 实现理论:
方法名称相同时,编译器会根据调用方法的参数个数,参数类型去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错
(二)方法的可变参数
可变参数(不定项参数):
JDK1.5开始,Java支持传递同类型的可变参数给一个方法
在方法声明中,在指定参数类型中加一个省略号(...)
一个方法中只能指定一个可变参数,他必须是方法的最后一个参数,普通参数声明必须在其之前
(三)方法的递归
递归就是:A方法调用A方法!就是自己调用自己
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大减少了程序的代码量。递归的能力在于用有限的语句定义对的无限集合。
递归结构包括两个部分:
(1)递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
(2)递归体:什么时候需要调用自身方法。
四、Java数组
(一)数组的概念
数组的定义:
数组是相同类型数据的有序集合。
数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问他们。
数组的四个基本特点:
(1)其长度是确定的。数组一旦被创建,它的大小就是不可以被改变的。
(2)其元素必须是相同类型,不允许出现混合类型。
(3)数组中的元素可以是任何数据类型,包括基本类型和引用类型。
(4)数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的。
(二)数组的使用
1. 数组初始化的方式:
(1) 静态初始化
int[] a = {1,2,3};
Man[] mans = {new Man(1,1),new Man(2,2)};
(2)动态初始化
int[] a = new int[2];
a[0]=1;
a[2]=2;
2. 数组的默认初始化:
数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中每个元素也被按照实例变量同样的方法被隐式初始化。
package array;
public class ArrayDemo01 {
public static void main(String[] args) {
//静态初始化:创建+ 赋值
int[] a = {1,2,3,4,5,6,7,8};
System.out.println(a[0]);
//动态初始化:包含默认初始化
int [] b = new int[20];
b[0] = 1;
System.out.println(b[0]);
System.out.println(b[1]);
System.out.println(b[2]);
System.out.println(b[3]);
}
}
- 数组堆栈分析:
//声明数组,array进入栈内存
int array = null;
//创建数组,new关键字操作进入堆内存中
array = new int[10];
//给数组元素中赋值
nums[0] = 1;
nums[1] = 2;
nums[2] = 3;
nums[3] = 4;
nums[4] = 5;
nums[5] = 6;
nums[6] = 7;
nums[7] = 8;
4. 数组边界:
下标的合法区间:[0,length-1],如果越界就会报错:
public class ArrayDemo02 {
public static void main(String[] args) {
int [] a = new int [2];
System.out.println(a[2]);
}
}
java.lang.ArrayIndexOutOfBoundsException:数组下标越界异常!
(三)小结
数组是相同数据类型(数据类型可以为任意类型)的有序集合。
数组也是对象。数组元素相当于对象的成员变量。
数组长度的确定性,不可变的,如果越界,则报:ArrayIndexOutOfBoundsException
数组的使用:
(1)普通的for循环
(2)For-Each循环
(3)数组做方法入参
(4)数组做返回值
public class ArrayDemo03 {
public static void main(String[] args) {
int[] arrays = {1,2,3,4,5};
//打印全部的数组元素
for(int i = 0;i<arrays.length;i++){
System.out.println(arrays[i]);
}
System.out.println("==================");
//计算所以元素的和
int sum = 0;
for(int i = 0;i < arrays.length;i++) {
sum += arrays[i];
}
System.out.println("sum="+sum);
System.out.println("=====================");
//查找最大元素
int max = arrays[0];
for (int i = 1;i<arrays.length;i++){
if(arrays[i]>max){
max = arrays[i];
}
}
System.out.println("max="+max);
}
}
public class ArrayDemo04 {
public static void main(String[] args) {
int[] arrays = {1,2,3,4,5};
int[] reverse = reverse(arrays);
printArray(reverse);
}
//反转数组
public static int[] reverse(int[] arrays){
int[] result = new int[arrays.length];
//反转操作
for (int i = 0,j = result.length-1; i < arrays.length; i++,j--){
result[j] = arrays[i];
}
return result;
}
//打印数组元素
public static void printArray(int[] arrays){
for (int i = 0; i < arrays.length;i++){
System.out.println(arrays[i]+"");
}
}
}
(四)多维数组
1. 多维数组:
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
2. 二维数组:
int a[][] = new int[2][5];
解析:二位数组a可以看成一个两行三列的数组。
3. 图解二位数组:
4. Arrays类:
数组的工具类java.util.Arrays(查看JDK帮助文档)
由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。
注意:Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用(注意:是“不用”而不是“不能”)
5. 具有以下常用功能:
给数组赋值:通过fill方法。
对数组排序:通过sort方法,按升序。
比较数组:通过equals方法对比数组中元素是否值得等待。
查找数据元素:通过biarySearch方法能对排序好的数组进行二分法查找法操作。
(五)排序算法和稀疏数组算法
1. 冒泡排序-时间复杂度为O(n2):冒泡排序是八大排序算法之一。
冒泡的代码还是相当简单的,两层循环,外层冒泡轮数 ,里面依次比较。
package array;
import java.lang.reflect.Array;
import java.util.Arrays;
//冒泡排序
//1.比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他的位置
//2.梅一次比较,都会产生一个最大,或者最小的数字;
//下一轮则可以少一次排序!
//4.依次循环,直到结束!
public class ArrayDemo06 {
public static void main(String[] args) {
int[] a = {1, 4, 5, 6, 72, 2, 2, 2, 25, 6, 7};
//调用完我们自己写的排序方法后,返回一个排序后的数组
int[] sort = sort(a);
System.out.println(Arrays.toString(sort));
}
public static int[] sort(int[] array) {
//临时变量
int temp = 0;
//外层循环,判断我们要循环多少次
for (int i = 0; i < array.length - 1; i++) {
//通过flag标识位减少没有意义的比较
boolean flag = false;
//内层循环,比价判断两个数,如果第一个数,比第二个数大,则交换位置
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 = true;
}
}
if (flag == false) {
break;
}
}
return array;
}
}
2. 稀疏数组:
当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方式是:
记录数组一共有几行几列,有多少不同值。
把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模。
package array;
public class ArrayDemo07 {
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();
}
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;
//遍历 二维数组,将非零的值,存放稀疏数组中
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]+"\t"
);
}
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 : array1) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
}
}
五、面向对象
(一)面向对象&面向过程
1. 面向过程思想:
步骤清晰简单,第一步做什么,第二部做什么...
面向过程适合处理一些较为简单的问题。
2. 面向对象思想:
物以类聚,分类的思维模式,解决问题首先会思考问题需要哪些分类,然后对这些分类进行独立思考。
最后,才对某个分了问题下的细节进行面向过程的思索。
面向对象适合处理复杂的问题,适合处理需要多人协作的问题。
对于描写复杂的事务,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
3. 面向对象编程(OOP)
面向对象编程的本质:以类的方式组织代码,以对象的形式封装数据
4. 抽象
(1)从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
(2)从代码运行的角度考虑是先有类后有对象。类是对象的模板。
(二)方法的调用
1. 静态方法和非静态方法(static修饰方法名)
(1)静态方法调用:类名.方法名
(2)非静态方法调用:实例化类(new)
//对象类型 对象名称 = 对象值
Student student = new Student();
//对象名字.方法名
student.say();
2. 值传递与引用传递
//值传递
public class Demo04{
public static void main(String[] args){
int a = 1;
System.out.println(a);//1
Demo04.change(a);
System.out.println(a);//1
}
public static void change(int a){
a = 10;
}
}
//引用传递:对象,本质还是值传递
//理解对象的概念,了解内存的知识
public class Demo05{
public static void main(String[] args){
Person person = mew Perosn();
System.out.println(person.name);//null
Demo05.change(person);
System.out.println(person.name);//111
}
public static void change(Person person){
//person是一个对象,指向的---->Person person = new Person();这是一个具体的人,可以改变属性!
person.name = "111";
}
}
class person{
String name;//null
}
3. 类与对象的创建
//学生类
public static Student(){
//属性:字段
String name;
int age;
//方法
public void study
/*this 关键字用来表示当前对象本身,或当前类的一个实例
通过 this 可以调用本对象的所有方法和属性。*/
System.out.println(this.name + "在学习");
}
public static void main(String[] args){
//类:抽象的,实例化
//类实例化后会返回一个自己的对象!
//student对象就是一个Student类的具体实例!
Student xm = new Student();
Student xh = new Student();
xm.name = "小明";
xm.age = "3";
System.out.println(xm.name);
System.out.println(xm.age);
xh.name = "小红";
xh.agh = "3";
System.out.println(xh.name);
System.out.println(xh.age);
}
}
4. 创建与初始化对象
使用new关键字创建对象
使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认初始化以及对类中构造器的调用。
5. 类的构造器也被称为构造方法,是在进行常见对象的时候必须调用的。并且构造器有以下几个特点:
1.必须和类的名字相同
2.必须没有返回类型,也不能写void
6. 作用:
(1)new本质就是在调用构造方法
(2)初始化对象的值
7. 注意点:
定义有参构造之后,如果想使用无参构造,显示的定义一个无参的构造(alt+ Insert)
public class Person {
String name ;
int age ;
public Person() {
}
//有参构造:一旦定义
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Application {
public static void main(String[] args) {
//实例化了一个对象
Person person = new Person( "aaaa " ,1);
System.out.println(person.name);
}
}
(三)封装
封装的概念:
该露的露,该藏的藏
我们的程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
封装(数据的隐藏)。通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
属性私有,get/set
(四)继承
1. 继承的概念:
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
extands的意思是“扩展”。子类是父类的扩展。
JAVA中类只有单继承,没有多继承!
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用extends来表示。子类和父类之间,从意义上讲应该具有“is a”的关系。
2. Object类
3. super注意点:
(1)super调用父类的构造方法,必须在构造方法的第一个。
(2)super必须只能出现在子类或者构造方法中!
(3)super和this不能同时调用构造方法!
4. super vs this:
(1)代表的对象不同:this本身调用者这个对象 / super代表父类对象的应用。
(2)前提:this没有继承也可以使用 / super只能在继承条件才可以使用。
(3)构造方法:this();本类的构造 / super();父类的构造。
5. 方法重写:需要有继承关系,子类重写父类的方法!
(1)方法名必须要相同
(2)参数列表必须相同。
(3)修饰符:范围可以扩大但不能缩小。 public>Protected>Default>private
(4)抛出的异常:范围,可以被缩小,但不能扩大。 ClassNotFoundException- >Exception(大)
重写,子类的方法必须要和父类一致,方法体不同!
6. 为什么要重写:
父类的功能,子类不一定需要,或者不一定满足!Alt+Insert; override;
(五)多态
1. 多态的概念
多态:即同一个方法可以根据发送对象的不同而采用多种不同的行为方式。
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关心的类)。
2. 多态存在的条件:
(1)有继承关系。
(2)子类重写父类方法。
(3)父类引用指向子类对象。
注意:多态是方法的多态,属性是没有多态性的。
3. instanceof(类型转换)引用类型,判断一个对象是什么类型:
(1)父类引用指向子类对象;
(2)把子类转换为父类,向上转型;
(3)把父类转换为子类,向下转型:强制转换
(4)方便方法的调用,减少重复的代码!