Java基本语法

特点

  1. 面向对象 oop

  2. 健壮,强类型机制

  3. 跨平台,即可以跨系统运行class文件,windows和Linux都可以

  4. Java语言是解释性的,JavaScript,PHP,java是解释性,编译性语言是c,c++

    解释性语言,编译后的代码不能直接被机器执行,需要解释器来执行

    编译性语言,编译后的代码可以直接被机器执行,编译后的是二进制文件,所以可以直接执行

Java的运行机制

  1. 先编写.java文件

  2. 编译为.class文件

  3. JVM,java虚拟机,因为有了JVM,同一个Java程序在三个不同的操作系统中都可以执行

JDK

  1. java development kit Java开发工具包

  2. JDK=JRE + Java的开发工具[java,javac,javadoc,javap等]

  3. jdk包含了jre,jre包含了jvm,所以安装了JDK,就不用安装JRE了

  4. 但是从jdk9开始,jdk目录中就没有单独的jre目录了,因为jre作为一个运行时,里面不需要包含太多的东西浪费空间,降低运行效率,再jdk9的时候使用模块化技术让开发者能按照自己的应用创建一个最小的运行时jre(比如一个微服务的部署,仅仅需要一个非常小的runtime,而不是像之前一样不管应用复杂还是简单,都需要一个近百M的jre运行),这样提高了运行效率

    javac 编译工具
    java 运行工具
    jdb 调试工具
    jhat 内存分析工具

JRE

  1. JRE = JVM + Java的核心类库
  2. java runtime environment Java运行环境
  3. 包括JVM和Java程序所需要的核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE

java快速入门

// 这是java快速入门

public class hello{

    //编写一个main方法
    public static void main(string[] args){
        System.out.println("hello,world~")
    }
}

表示hello是一个类,是public公有的类,这个类的名字要和文件名相同

  1. 大括号表示一个类的开始和结束,hello{}表示一个类的开始和结束

  2. public static void main()表示是一个主方法,即我们程序的入口

  3. main(){…}大括号表示方法的开始和结束

  4. System.out.println(“hello world“);表示输出”hello,world“到屏幕

  5. 分号**;**代表语句的结束

  6. 如果程序class后的变量和文件名不一致,会报错“错误: 类HelloWorld是公共的, 应在名为 HelloWorld.java 的文件中声明”,这个时候,我们需要将文件名和类名相同

编码问题

  1. 出现乱码编译不过去,javac编译之后没有.class文件的原因可能就是编码问题

  2. win+r打开terminal,右键点击属性,可以查看到编码(当前代码页那一栏)

  3. 因为当前控制台设置的编码是gbk,所以只认gbk,其它的编码无法识别,即无法过编译

  4. 所以在vscode中ctrl+shift+p,打开控制台,编码,选择编码重新打开,使用和terminal一样的编码打开,(可以都用gbk)

运行问题

  1. javac 加上文件名可以编译

  2. java 加上类的名字可以运行

  3. 注意,在运行的时候不能加.class,因为开发者写底层代码的时候,实际运行的是某个类,而不是某个文件

  4. 如果想要类名和文件名不一致,必须在声明类时不带public,例如:

    public class Demo{} -> class Demo{}
  5. 一个java文件中可以写多个class类但是只能有一个类带public,有多少类就会生成多少class文件

  6. main方法必须写在带public的类中

Java执行流程分析

  1. 编写.java文件(源文件)
  2. 用javac命令将上一步编写的.java文件编译为.class文件(字节码文件)(javac命令的本质就是调用javac.exe)
  3. 用java命令运行出结果,运行的本质就是将.class文件装载到jvm虚拟机中执行
  4. 每一次更改之后必须重新编译,将jvm中的.class文件进行更新,才能真正地输出更新之后的结果,否则只保存,不会更新

Java开发细节

  1. Java源文件以.java为拓展名,源文件的基本组成部分是类(class),例如本类中的Hello类

  2. Java应用程序的执行入口是main()方法,有固定的书写格式

    public static void main(String[] args){...}
  3. Java严格区分大小写

  4. Java每一条语句都是以分号结尾

  5. 大括号都是成对出现的,缺一不可,习惯先写{}再写代码

  6. 一个源文件最多只能有一个public类,其它类的个数不限,例如我只能写一个public类,然后写多个前面没有限制的类

  7. 编译后,每一个类,都对应一个.class文件

  8. 如果源文件包含一个public类,则文件名必须按照该类名命名类的名字决定了文件名

  9. 一个源文件最多只能有一个public类,其它类的个数不限,也可以将main方法卸载非public类中,然后指定运行非public类,这样入口方法就是非public的main方法,而且一个源文件中可以包含多个main方法,即可以在public类中写完main后,在其它类中接着写main方法

  10. 因为javac编译后是一个个的.class文件,调用时是单个进行调用,所以调用时,需要使用 java + 类名 进行逐个调用

  11. 类、方法的注释,要以javadoc的方式来写

  12. 非javadoc的注释,往往是给代码的维护者看的,着重告诉读者为什么这样写,如何修改,注意什么问题

  13. 码风缩进问题:选中后,按tab键整体右移,选中后,按shift+tab整体左移

  14. 码风书写问题:运算符和 = 两边各习惯性地加一个空格,比如 2 + 4 * 5 + 345 - 89

  15. 源文件使用utf-8编码,用gbk是用dos不得已使用,所以以后开发使用utf-8编码

  16. 行宽不要超过80个字符,每一行不要超过80个字符

  17. 代码编写次行风格行尾风格

学习方法

  1. 按需学习

  2. 先看看学过的传统技术能不能解决,新技术和传统技术进行比较,能解决但是不完美还是不能解决

  3. 引出我们学习的新技术和知识点

  4. 学习新技术或者知识点的基本原理和基本语法,不要在一开始就考虑细节

  5. 快速入门(基本程序,增删改查)

  6. 开始考虑研究技术的注意事项,使用细节,使用规范,如何优化,研究框架之类的放到最后

Java转义字符

\t 制表符
\n 换行,注意和\r的区别
\\ 一个\
\" 一个"
\' 一个'
\r 将光标跳转到该行开头,reverse,只是回车,没有换行,而且不是删除该行后,是替换前面的字符,而不是删除

初学Java易犯错误

  1. 找不到文件:文件名字写错了,或者终端的当前位置不对
  2. 主类名和文件名不一致
  3. 缺少分号

Java基本概念(第一个Java程序)

概念

  1. 对象:对象是类的一个实例,有状态和行为。例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。
  2. 类:类是一个模板,描述一类对象的行为和状态
  3. 方法:方法就是行为,一个类可以有很多方法。逻辑运算,数据修改以及所有动作都是在方法中完成的。
  4. 实例变量:每个对象都有独特的实例变量,对象的状态由这些实例变量的值决定。

第一个Java程序

  1. public class Demo03Helloworld:定义一个类
  2. class:代表的就是类,类是Java程序最基本的组成单元,所有代码都需要在class中写
  3. class后面跟的名字叫做类名,要求类名和Java文件名保持一致
  4. public static void main(String[] args):叫做main方法,是程序的入口,jvm执行代码,会从main开始执行
  5. System和String的首字母S要大写

养成习惯

  1. 大小写敏感:Java是大小写敏感的
  2. 类名:对于所有类来说,类名的首字母应该大写。如果类名由若干单词组成,那么每个单词的首字母都应该大写,My First Java Class
  3. 方法名:所有的方法名都应该以小写字母开头,如果方法名含有若干单词,则后面的每个单词首字母大写(只是第一个单词小写,后面的每一个单词的首字母都要大写)
  4. 源文件名:源文件名必须和类名相同,当保存文件时,应该使用类名作为文件名保存
  5. 主方法入口:所有的Java程序都是由public static void main(String[] args)方法开始执行

Java标识符

  1. 类名,变量名,方法名都被称作标识符

  2. 所有标识符都应以字母,美元符,或者下划线作为首字母,不能用数字作为标识符的首字母

    [a-z][A-Z] $ _
  3. 首字母之后可以是字母,美元符,下划线和数字的任何字符组合

  4. 关键字不能用作标识符

  5. 大小写敏感

关键字

注释

  1. 单行注释 //
  2. 多行注释 /* */,多行注释里面不允许由多行注释嵌套
  3. 文档注释/** */,第二个星号和第三个星号之间写注释内容

文档注释

  1. 注释内容可以被JDK提供的工具javadoc所解析,生成一套以网页文件型式体现的该程序的说明文档,一般写在类

  2. 可以使用javadoc工具来生成信息,并且输出到HTML文件中。

  3. 常用的标签

    @author @exception @link @return @see @serial @version
  4. javadoc标签

  5. 由 /** 开始 由 */结束,在开始的/**之后,第一行或几行是关于类,变量,和方法的主要描述,可以不加@标签写非标签的注释

  6. 之后可以包含一个或多个各式各样的**@标签**,每一个@标签必须在一个新行的开始或者在一行的开始紧跟星号 *

    /***这是一个javadoc
    * @author runoob
    * @version 1.2
    */
  7. javadoc的输出:javadoc将你的Java程序的源代码作为输入,输出一些包含你程序注释的HTML文件

  8. 每一个类的信息将在独自的HTML文件里,javadoc也可以输出继承的树形结构和索引

  9. 由于javadoc的实现不同,工作也可能不同

  10. 每一个javadoc文档注释都在描述的项目的前面

  11. 可以在每一个class中都写一个javadoc

  12. 结果将在 class名字.html 中找到

基本数据类型

两大数据类型

  1. 内置数据类型
  2. 引用数据类型

内置数据类型

  1. 8种基本类型:6种数字类型,1种字符类型,1种bool类型
byte 8位,有符号的,以二进制补码表示的整数
short 16int 32long 64float 32
double 64
boolean 只有两个取值,truefalse,表示一位的信息,默认值为false
char 16

引用类型

  1. 在Java中,引用类型的变量非常类似于C/C++的指针。
  2. 引用类型指向一个对象,指向对象的变量是引用变量。
  3. 这些变量在声明时被指定为一个特定的类型,比如 Employee、Puppy 等。变量一旦声明后,类型就不能被改变了。
  4. 简单地说,就是自己写的对象和数组就是引用数据类型
  5. 所有引用类型的默认值都为null

java常量

  1. 在Java中使用final关键字来修饰常量,声明方式就是在变量声明方式前面加上final

    final double PI = 3.14
  2. 用0来表示8进制,0x表示16进制,不能是o和O

  3. 字符串常量和字符变量都可以包含任何 Unicode 字符。

自动类型转换

  1. 整型,实型,字符型数据可以混合运算,运算中,不同类型的数据先转换为同一类型,然后进行运算

  2. 转换从低级到高级

    ------------------------------------>byte,short,char> int> long> float> double 

    转换规则

    1. 不能对bool类型进行转换
    2. 不能把对象类型转换成不相关类的对象。???
    3. 在把容量大的类型转换为容量小的类型时必须使用强制类型转换
    4. 转换过程中可能出现溢出或者精度损失
    5. 浮点数转换为整数时通过舍弃小数得到,而不是四舍五入
    6. 该区域的数据/值可以在同一类型范围内不断变化

强制类型转换

  1. 条件是转换的数据类型必须是兼容的

  2. 格式

    (type)value
    int i1 = 123;
    byte b = (byte)i1;

基本数据类型和String类型的转换

基本数据类型转String类型

  1. 语法:将基本类型的值 + ”“ 即可

    public class StringToBasic{
        public static void main(String[] args){
            int n1 = 100;
            String str1 = n1 + "";
            String str2 = "abc";
            System.out.println(str1 + " " + str2);
        }
    }
  2. 注意这个地方的String的首字母是大写的

String类型转基本数据类型

  1. 语法:通过基本类型的包装类调用parseXXX方法即可

    public class StringToBasic{
        public static void main(String[] args){
            String s1 = "100";
            int a = Integer.parseInt(s1);
            System.out.println(s1);
        }
    }
  2. parse:解析,parseInt:将字符串参数作为有符号的十进制整数进行解析,除了第一个字符可以是用来表示负值的ASCII减号外,其余的字符串中的字符都必须是十进制整数。

  3. parseDouble:

    public class StringToBasic{
        public static void main(String[] args){
            String s1 = "123.111";
            double dou1 = Double.parseDouble(s1);
            System.out.println(dou1);
        }
    }
  4. 还有Float.parseFloat , Long.parseLong,Byte.parseByte等等

常量运算除法特殊

  1. 前后如果都是整数,结果只取整数部分

  2. 前后只要有一个带小数点,结果就是正常小数了

  3. ```java
    System.out.println(“10/3”) //结果为3,不为小数
    System.out.println(“10.0/3”) //结果为小数
    System.out.println(“10/3.0”) //结果为小数

    
    
    
    ## 变量类型
    
    1.   使用逗号来隔开声明多个同类型变量,和c不同的是:可以在定义多个变量的同时,写到一行,统一赋值
    
         ```java
         int a, b, c;         // 声明三个int型整数:a、 b、c
         int d = 3, e = 4, f = 5; // 声明三个整数并赋予初值
         byte z = 22;         // 声明并初始化 z
         String s = "runoob";  // 声明并初始化字符串 s
         double pi = 3.14159; // 声明了双精度浮点型变量 pi
         char x = 'x';        // 声明变量 x 的值是字符 'x'。

java支持的变量类型

  1. 类变量:独立于方法之外的变量,用static修饰

  2. 实例变量:独立于方法之外的变量,不过没有static修饰

  3. 局部变量:类的方法中的变量

    public class Variable{
    	static int a = 1; //类变量
    	String str="hello world"; //实例变量
    	public void method(){
    		int i = 0;  //局部变量
    	}
    }

局部变量

  1. 局部变量在方法,构造方法,或者语句块被执行的时候创建,当他们执行完后,变量会自动销毁
  2. 访问修饰符不能用于局部变量 ???
  3. 局部变量只在声明它的方法、构造方法或者语句块中可见
  4. 局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才能使用

实例变量

  1. 实例变量声明在一个类中,但在方法、构造方法和语句块之外
  2. 当一个对象被实例化之后,每个实例对象的值就跟着确定
  3. 实例对象的在对象创建的时候创建,在对象销毁的时候销毁
  4. 实例对象的值至少应该被一个方法,构造方法或者语句块引用,使得外部能够通过这些方式获取实例变量信息
  5. 实例对象可以声明在使用前和使用后

类变量,静态变量

  1. 类变量也称为静态变量,在类中以 static 关键字声明,但必须在方法之外。
  2. 无论一个类创建了多少个对象,类只拥有类变量的一份拷贝。
  3. 静态变量除了被声明为常量外很少使用,静态变量是指声明为 public/private,final 和 static 类型的变量。静态变量初始化后不可改变。

常量和静态变量的区别

  1. 常量前面用final修饰,静态变量前面用static修饰

(94条消息) 静态变量和常量的区别_haobaworenle的博客-CSDN博客_静态变量和常量有什么区别

静态变量和实例变量的区别

  1. 语法上:静态变量前面用static关键字,实例变量前面不用

  2. 实例变量属于某个实例对象,只有当实例化后才能创建实例变量

  3. 而静态变量不属于实例对象,而是属于类,只要程序加载了类的字节码,不用创建实例对象,就会被分配空间,静态变量就能使用

    (94条消息) 静态变量和实例变量的区别_韩金群的博客-CSDN博客_静态变量和实例变量的区别

Java修饰符

  1. 修饰符用来定义类、方法或者变量,通常放在语句的最前端。

访问修饰符

  1. Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。

运算符

>>> 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以0补充
>> 按位右移操作符,移动得到的左边空位不会以0补充
  1. 注意逻辑运算符 && 和 || 带来的短路特性

instanceof 运算符

  1. 该运算符用于操作对象实例,检查该对象是否是一个特定的类型。

  2. 例如,检查是否为int类型,就是 var instanceof int,返回值是一个bool值,true或false,所以可以判断对象的类型(类类型或接口类型)

    String name = "James";
    boolean result = name instanceof String; //由于name是String类型,所以返回值为true
  3. 如果被比较的对象兼容右侧类型,该运算符仍然返回true,例如下面的例子,子类继承了父类,所以兼容于父类,所以子类instanceof父类

    class Vehicle{}
    public class Car extends Vehicle{
    	public static void main(String[] args){
    		Vehicle a = new Car();
    		boolean result = a instanceof Car;
    		System.out.println(result);
    	}
    }

循环结构

  1. while
  2. do while
  3. for
  4. break
  5. continue
public class Test{
	public static void main(String[] args){
		int x = 10;
	}
	do{
		System.out.println("value of x : " + x);
		x++;
		System.out.println("\n");
	}while(x < 20);
}
public class Test{
	public static void main(String[] args){
		int x = 10;
		while (x < 20){
			System.out.println("value of x :" + x); //这个地方的 string + x 的用法和一个整数 + ""可以成为字符串一样
			x++;
			System.out.println("\n");
		}
	}
}
public class Test{
	public static void main(String[] args){
		int [] numbers = {10,20,30,40,50};
		for(int x : numbers){
			System.out.println(x);
			System.out.println(" , ");
		}
        System.out.println("\n");
        String [] names = {"james","Larry","TOM"};
        for(int x : names){
            System.out.println(x);
            System.out.println(" , ");
        }
        System.out.println("\n");
	}
}
  1. 上面for循环使用的是类似于c++的范围遍历的增强型for循环

  2. 声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配,其作用域限定在循环语句块,其值与此时数组元素的值相等

  3. 表达式:表达式是要访问的数组名,或者是返回值为数组的方法

    for(声明语句 : 表达式){
    	//代码语句;
    }
  4. break主要用于循环语句或者switch语句中,用来跳出整个语句块

  5. break跳出最里层的循环,并且继续执行该循环下面的语句(执行该层循环之外的其它语句,跳出此循环)

    public class Test{
    	public static void main(String[] args){
    		int [] numbers = {1,2,3,4,5};
    		for (int x : numbers){
    			if(x == 3){
    				break;
    			}
    			System.out.println(x);
    			System.out.println("\n");
    		}
    	}
    }
  6. continue 让程序立刻跳转到下一次循环的迭代,而不是跳出整个循环

  7. 在for循环中,continue使程序立即跳转到更新语句

  8. while和do while中,程序立即跳转到bool表达式的判断语句

    public class Test{
        public static void main(String[] args){
            int [] numbers = {10, 20, 30, 40, 50};
            for(int x : numbers){
                if(x == 30){
                    continue;
                }
                System.out.print(x);
            }
    
            System.out.println("\n");
        }
    }

条件语句

  1. if else
  2. switch case
  3. if ,else if, else
public class Test{
    public static void main(String[] args){
        int x = 10;
        if (x < 20){
            String a = "yes";
            System.out.println(a);
        }
        else{
            String a = "false";
            System.out.println(a);
        }
    }
}
public class Test{
	public static void main(String[] args){
        int x = 30;
        if(x == 10){
            System.out.println("10");
        }
        else if(x == 20){
            System.out.println("20");
        }
        else{
            System.out.println(x);
        }
    }
}
  1. 注意default的先后顺序:先全部判断一遍case语句,在没有case语句的值和变量值相等时执行,default分支不需要break
public class Test{
    public static void main(String[] args){
        char grade = 'C';
        switch(grade){
            case 'A' :
                System.out.println('A');
                break;
            case 'B' :
                System.out.println('B');
                break;
            case 'C' :
                System.out.println('C');
                break;
            default : 
                System.out.println("未知等级");
        }
    }
}

return

  1. return 语句如果用在main函数中,则会跳出程序

    public class Return {
        public static void main(String[] args) {
            int x = 0;
            for (int a = 0; a <= 10; a++) {
                x += a;
                if (x == 3) {
                    System.out.println(x);
                    return;
                }
            }
        }
    }

String类

  1. 在Java中字符串属于对象,Java提供了String类来创建和操作字符串。

  2. 创建字符串

    String str = "Runoob";
  3. 也可以和其它对象一样,使用关键字和构造方法来创建String对象

    String str2 = new String("Runoob");
  4. String创建的字符串存储在公共池中,而new创建的字符串对象在堆上

  5. 注意:String类是不可改变的,所以一旦创建了String对象,那么它的值就无法改变了。

  6. 如果需要对字符串做很多修改,那么应该选择使用 StringBuffer & StringBuilder 类

获取字符串长度

  1. 使用length方法,获取有关对象的信息的方法被称为访问器方法

  2. 语法:

    int len = str_name.length;
    1. 注意:对象.length,后面不加括号

    连接字符串

    1. 使用concat连接字符串

      string1.concat(string2);
      "我的名字是".concat("syk");
    2. 使用 + 操作符来连接字符串

      "Hello" + "syk" + "!";

键盘输入语句

  1. 在input.java中,需要一个扫描器(对象),Scanner,来接收用户输入的数据,使用键盘输入语句来获取

  2. 步骤

    1. 导入该类的所在包,java.util.*  要引用一个类,就必须导入一个包
    2. 创建该类的对象(声明变量)
    3. 调用里面的功能
  3. ```java
    import java.util.Scanner;

    public class Input {

      public static void main(String[] args) {
          Scanner scanner = new Scanner(System.in); // new创建一个对象,最前面的是表明是Scanner类的名字为scanner的变量
          System.out.println("请输入名字");
          String name = scanner.next(); // next()是查找并返回来自此扫描器的下一个完整标记
          System.out.println("请输入年龄");
          int age = scanner.nextInt();
          System.out.println("名字为" + name + "年龄为" + age);
      }
    

    }

    
    5.   scanner是一个简单的文本扫描器
    
    6.   ```java
         import java.util.Scanner;
         Scanner scanner = new Scanner(System.in);
         datatype name = scanner.next(); // scanner.next(); 默认是string
         datatype name = scanner.nextInt(); // scanner.nextInt(); 只有表明是Int才会接收int
         datatype name = scanner.nextDouble(); // 只有表明是Double,才会接收double类型的数据

数组

声明数组变量

  1. 首先必须声明数组变量,才能在程序中使用数组。

    datatype[] array;
    datatype array[];

    建议使用datatype[] array_name的声明风格声明数组变量。 dataType arrayRefVar[] 风格是来自 C/C++ 语言 ,在Java中采用是为了让 C/C++ 程序员能够快速理解java语言。

创建数组

  1. Java使用new操作符来创建数组

    array_name = new datatype[arraysize];
  2. 上面语法做了两件事,第一:使用datatype[size]创建了一个数组,第二:把新创建的数组引用复制给变量array——name

声明和创建数组一步完成

datatype[] array_name

数组的引用

  1. 引用,使用,访问,获取 是一个意思

数组的动态初始化1

datatype[] name = new datatype[size];

数组的动态初始化2

  1. 有些时候可以在for循环的外面声明一个数组,但是分配内存是当某个条件满足的时候才去真正分配
  2. 第一步,先声明数组(声明时还没有分配空间,声明数组的名字的指针还没有指向任何空间)
  3. 此时该数组时null
int[] a;
int a[];
  1. 第二步,创建数组

  2. 只有new之后,才会分配内存空间,可以存放数据

    数组名 = new 数据类型[大小];
    a = new int[10];

数组的静态初始化

int a[] = {1,2,3...};
  1. 上面的用法等同于

    int[] a;
    a = new int[n];
    a[0]=1; a[1]=2;...
  2. 当知道数组有多少元素,具体值时才用静态方法初始化数组

数组detail

  1. 数组中的元素是相同类型的,如果在低精度数组中写了一个高精度数组,则会报错;如果在一个高精度数组中写了一个低精度数组,没有问题,自动转换

    detail.java:3: 错误: 不兼容的类型:double转换到int可能会有损失
            int a[] = { 1, 2, 3,3.3 };
                                ^
    1 个错误
  2. 数组下标必须在指定范围内使用,否则报:下标越界异常,比如 int[] arr = new int[5];则有效下标是0-4,即数组的下标,最小是0,最大是数组长度-1,否则数组越界,在编译的时候不会报错,当运行的时候才会报错

    java.lang.ArrayIndexOutOfBoundsException
  3. 数组属于引用类型,数组行数据是对象

数组的赋值机制

基本数据类型的赋值,拷贝赋值

  1. 基本数据类型的赋值,赋值方式为拷贝

  2. n2的变化不会影响到n1

    int n1 = 10;
    int n2 = n1;
    int n2 = 1; //此时n1还是10,n2变为了1

数组赋值,引用赋值

  1. 数组在默认情况下是引用传递,赋的值是地址,赋值方式为引用赋值

  2. 引用赋值传递的是一个地址,arr2和arr1指向的是同一个地址,所以当对arr2的数组进行操作时,会对arr1产生影响

    public class detail {
        public static void main(String[] args) {
            int[] arr1 = {1,2,3};
            int[] arr2 = arr1;
            arr2[0] = 10;
            for(int i = 0;i < arr1.length;i++){
                System.out.println(arr1[i]); //这个时候就会输出10,2,
            }
        }
    }

拷贝赋值和引用赋值的区别

  1. jvm的内存分为:栈、堆、方法区

  2. 基本数据类型直接放在栈中,即值拷贝/传递在栈中进行

  3. 数组在定义的时候,赋的值并不是具体的值,而是一个地址,这个地址指向的时是堆中的一片空间

  4. 在内存中,只要分配了一个数据空间,一定会对应一个地址

  5. 引用传递也叫地址拷贝

数组拷贝

  1. 将int[] arr1 = {1,2,3} 拷贝到 arr2数组,要求数据空间是独立的

  2. ```java
    int[] arr1 = {1,2,3};
    int[] arr2 = new int[arr1.length];
    // 遍历arr1,把每个元素拷贝到对应元素的位置
    for(int i = 0;i < arr1.length;i++){

      arr2[i] = arr1[i];
    

    }

    
    
    
    ### 处理数组
    
    1.   数组的元素类型和数组的大小都是确定的,所以当处理数组元素时候,我们通常使用基本循环或者 For-Each 循环。、
    
    #### For-each循环
    
    1.   For-each循环,加强型循环,可以在不使用下标的情况下遍历数组
    
         ```java
         for(type element : array){
         	System.out.println(element);
         }
    public class Testarray {
        public static void main(String[] args) {
            double[] myList = { 1.9, 2.9, 3.4, 3.5 };
            for (double x : myList) {
                System.out.println(x);
            }
        }
    }

数组作为函数的参数

  1. 数组可以作为参数传递给方法

    public class Print {
        public static void main(String[] args){
            printArray(new double[]{1.2,1.2,3.3,44.4});
        }
    
    
        public static void printArray(double[] array) {
            for (int i = 0; i < array.length; i++) {
                System.out.println(array[i] + " ");
            }
        }
    }

数组作为函数的返回值

  1. 数组作为函数的返回值,return返回的是一个地址
  2. 函数的返回值标明数据类型,int[] double[] float[]
public static int[] reverse(int[] list){
    int result = new int[list.length];
    for(int i = 0,j = result.length - 1;i < list.length;i++,j--){
        result[j] = list[i];
    }
    return result;
}

多维数组

  1. 数组的数组

    String[][] str = new String[3][4];

多维数组的动态初始化基础

  1. 直接为每一维度分配空间

    type[][] typename = new type[typelength][typelength]
  2. 从最高维开始,分别为每一维分配空间

    String[][] s = new String[2][];
    s[0] = new String[2];
    s[1] = new String[3];
    s[0][0] = new String("Good");
    s[0][1] = new String("Luck");
    s[1][0] = new String("to");
    s[1][1] = new String("you");
    s[1][2] = new String("!");

具体实现

public class Doublearr {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // 静态初始化方法1
        int c[][] = new int[2][3]; // 直接将行和宽定义出来的静态初始化

        // 静态初始化2
        int[][] d = { { 1, 1, 1, 1 },
                { 2, 2, 2, 2, 2 },
                { 3, 3, 3, 3, 3, 3 },
        };

        // 动态初始化1
        // 先声明这是一个二维数组,然后再使用new来定义(开辟空间)
        int a[][]; // 先声明这是一个二维数组
        a = new int[2][3]; // 再用new去开辟空间

        // 动态初始化2
        // 可以出现列数不确定的情况(行数必须确定)
        // 即数组的第一维必须指出,第二维可以不写
        int arr[][] = new int[5][]; // 第二维可以不去定义
        for (int i = 0; i < arr.length; i++) { // 遍历arr的每一个一维数组
            // 给每个一维数组开空间
            // 如果没有给一维数组new,那么arr[i]就是null
            arr[i] = new int[i + 1];
            for (int j = 0; j < arr[i].length; j++) {
                arr[i][j] = j;
                System.out.print(arr[i][j]);
            }
            System.out.println();
        }
        System.out.println(arr.length);
    }
}

逆序数组

思路1

  1. 把arr[0]和arr[n-1]进行交换,双指针

  2. ```
    public class Reverse {

      public static void main(String[] args) {
          int[] arr = { 1, 2, 3, 4, 5 };
          int temp = 0;
          int len = arr.length;
          for(int i = 0;i < arr.length / 2;i++){
              temp = arr[len - 1 - i];
              arr[len - 1 - i] = arr[i];
              arr[i] = temp;
          }
    
          for (int x : arr) {
              System.out.print(x);
          }
      }
    

    }

    
    3.   还有一种是重新开辟内存空间,逆序遍历arr,将每个元素拷贝到arr2的元素中(逆序遍历,顺序拷贝)
    
    ```java
    public class Arrreverse {
        public static void main(String[] args) {
            int[] arr1 = { 1, 2, 3, 4, 5 };
            int[] arr2 = new int[arr1.length];
            for (int i = arr1.length - 1,j = 0; i >= 0; i--,j++) { //注意,当一重循环中有多个循环变量时,只需要定义一次循环变量的类型,例如已经定义了int i,就不能再定义j 为int 了,默认为相同类型
                arr2[j] = arr1[i];
            }
            for (int x : arr2) {
                System.out.print(x);
            }
        }
    }

数组添加1

  1. 要求:实现动态地给数组添加元素效果,实现对数组的扩容。

    原始的数组使用静态分配 int[] arr = {1,2,3};
    增加元素,直接放在数组的最后 arr_new = {1,2,3,4};
  2. 注意:静态初始化的数组下标的最大值和最小值已经固定,如果强制赋值,例如上面的例子,arr[3] = 4,会报数组越界的错误,即静态数组的大小不能改变

  3. 思路:定义一个新的数组,int[] arrNew = new int[arr.length + 1]; 令新数组扩容

  4. 然后遍历arr数组,依次将arr元素拷贝到arrNew数组

  5. 将4赋值给arrNew[arrNew.length - 1];

  6. 体现是改变的原来的数组,而不是新数组,最后要让arrNew指向原先的arr

    arr = arrNew;
  7. 原来的没有被引用的空间就会被销毁

public class Up{
	public static void main(String[] args){
		int[] arr = {1,2,3};
		int[] arr_new = new int[arr.length + 1];
		for(int i = 0;i < arr.length;i++){
			arr_new[i] = arr[i];
		}
		arr_new[arr_new.length - 1] = 4;
		// 让arr 指向arr_new
	    arr = arr_new;
		for(int x : arr){
			System.out.print(x);
		}
	}

}

数组扩容2

  1. 使用户可以动态添加元素进数组

    1. 创建一个Scanner可以接受用户输入
    2. 因为用户什么时候退出,不确定,使用do-while + break来控制
  2. ```java
    import java.util.Scanner;

    public class Up {

      public static void main(String[] args) {
          Scanner myscanner = new Scanner(System.in);
          int[] arr = { 1, 2, 3 };
          do {
              int[] arrNew = new int[arr.length + 1];// 先扩容
              for (int i = 0; i < arr.length; i++) { // 再通过遍历,逐个赋值给arrNew
                  arrNew[i] = arr[i];
              }
              System.out.println("请输入你要添加的元素");
              int num = myscanner.nextInt();
              arrNew[arrNew.length - 1] = myscanner.nextInt();// 添加最后一个元素
              arr = arrNew;
              // 询问客户是否还要继续添加
              if (num == 1) {
                  break;
              }
    
          } while (true);
          for (int x : arr) {
              System.out.print(x);
          }
      }
    

    }

    
    #### 数组缩减
    
    ```java
    import java.util.Scanner;
    public class Reduce {
        public static void main(String[] args){
            int[] arr = {1,2,3,4,5};
            Scanner myscanner = new Scanner(System.in);
            String a;
            do{
                a = myscanner.next();
                int[] arrNew = new int[arr.length - 1];
                for(int i = 0;i < arr.length - 1;i ++){
                    arrNew[i] = arr[i];
                }
                arr = arrNew;
            }while(a != "1"); //while内部写的是执行循环的条件,是令循环继续下去的条件
            for(int x : arr){
                System.out.print(x);
            }
        }
    }
  3. 和数组扩容的思路相同

acwing补充

Java和c++,python的不同点

  1. java中的函数必须定义到类中
  2. c++的函数可以定义到类外面

static

  1. 一个方法如果加上了static,那么这个方法就是绑定到了类本身
  2. 和global类似
  3. static的意思是从这个类实例化出来的对象共享属性
  4. 类方法和类变量
  5. 静态方法中必须只能调用静态方法和静态属性,不能调用非静态的,即必须加上static

接口

  1. 接口就是用来规范化方法的
  2. 接口虽然是类,但是不能实例化
  3. 接口只是对方法进行一个声明,不能具体写实现方法
  4. 所有implements接口的类必须实现所有接口中的所有方法都实现,接口中的方法都是abstract的,即没有具体写明的

继承

  1. 如果一个游戏有很多英雄
  2. 英雄有公共(都有)的技能
  3. 那么其它英雄的技能可以继承自一个基类,这个基类中写共有的方法
  4. 基类就是父类
  5. 继承的作用就是为了不去重复写,公共的放到父类中去

多态

  1. 同一个类的同一个函数可能会有不同的行为