Java SE进阶笔记(更新ing)

本文详细介绍了Java中的IDEA使用、快捷键操作,深入讲解了final关键字、抽象类、接口、包机制、访问权限控制符、Object类的方法,以及匿名内部类。还探讨了一维数组的声明、初始化和操作。内容涵盖了面向对象编程的基础和核心概念,有助于深入理解Java编程。
摘要由CSDN通过智能技术生成

零、IDEA集成开发环境

0.1 IDEA的使用

1.用IDEA打开一个文件目录,创建一个项目project
为项目命名
2.为项目命名
为项目命名
3.弹出一个项目结构,点击Cancel关闭
弹出一个项目结构,点击Cancel关闭
4.创建一个模块module
点击下一步
5.点击下一步
点击下一步
6.为模块命名
为模块命名
7.在创建的模块下的src中创建Java Class类
在创建的模块下的src中创建Java Class类
8.创建完成
创建完成

0.2快捷键

1.快速生成main方法:psvm或main
2.快速生成输入语句:sout
3.删除一行:Ctrl+Y
4.左侧列表可以通过方向键操作开合,左键关,右键开,上下键移动
5.任何新增、新建、添加的快捷键:Alt+Insert
6.窗口变大小:Ctrl+Shift+F12
7.切窗口:Alt+左右箭头
8.运行:Ctrl+Shift+F10
9.单行注释:Ctrl+/
10.多行注释:Ctrl+Shift+/
11.定位方法属性变量:停到单词下按Ctrl,点击跳转
12.纠正错误 Alt+Enter

一、面向对象

1.1 final关键字

  • final修饰的变量不能被修改
  • final修饰的变量必须被显示初始化
  • final修饰的方法不能被覆盖
  • final修饰的类不能被继承
  • 如果修饰的引用,那这个引用只能指向一个对象,但是被指向的对象可以修改
  • 构造方法不能被final修饰

1.1.1 final修饰的局部变量不能被修改

示例程序:

public class Test {
    public static void main(String[] args) {
        final int k = 10;
        k = 20;
    }
}

运行结果:

java: 无法为最终变量k分配值

1.1.2 final修饰的实例变量

系统不会自动赋默认值,必须手动赋一个值(在构造方法里赋值也行)

示例程序:

public class Test {
    public static void main(String[] args) {

    }
}
class Person{
    final int age = 0;//手动赋值
    final boolean sex;//被final修饰的实例变量必须手动赋值,系统不会自动赋默认值
    public Person(){
		this.sex = true;//手动赋值
	}
    
}

实例变量被final关键字修饰后,一般会加static变为静态
static final修饰的变量称为常量,常量不可更改,一般为公开的

示例程序:

public class Test {
    public static void main(String[] args) {

    }
}
class Chinese{
    String idCard;
    String name;
    static final String COUNTRY = "中国";
}

1.1.3 final修饰的引用变量不能被修改

该引用内部的数据是可以被修改的

示例程序:

public class Test {
    public static void main(String[] args) {
        final Person p = new Person(30);//该引用只能指向一个对象,并且永远只指向这个对象
        p = new Person(30);//p引用保存的地址是不可修改的
        System.out.println(p.age);
        p.age = 40;//引用内部的数据是可以被修改的
        System.out.println(p.age);
    }
}
class Person{
    int age;

    public Person() {
    }

    public Person(int age) {
        this.age = age;
    }
}

运行结果:

java: 无法为最终变量p分配值

1.1.4 final关键字修饰的类不能被继承

示例程序:

final class A{

}
class B extends A{

}

运行结果:

java: 无法从最终A进行继承

1.1.5 final修饰的方法不能被覆盖重写

示例程序:

public class Test {
    public static void main(String[] args) {

    }
}
class A{
    public final void doSome(){

    }
}
class B extends A{
    public  void doSome(){

    }
}

运行结果:

java: B中的doSome()无法覆盖A中的doSome()
  被覆盖的方法为final

1.2 抽象类

抽象类是类和类之间有共同特征再抽象成抽象类

  • 在Java中采用abstract定义的类就是抽象类,采用abstract定义的方法就叫抽象方法
  • 抽象类属于引用数据类型
  • 抽象方法只能存在于抽象类中
  • 抽象父类中有抽象方法,继承的子类要么也为抽象类,要么在子类中覆盖抽象方法
  • 抽象类无法实例化,无法创建对象
  • 抽象类不能用final修饰,抽象类就是用来被继承的
  • 抽象方法不能被final修饰
  • 向上转型多态编译时,会绑定父类中的方法,在执行时会执行子类的。

1.2.1 采用abstract定义抽象类

抽象类定义的语法格式:

[修饰符列表] abstract class 类名{
	类体;
}

1.2.2 抽象方法

抽象方法表示没有实现的方法没有方法体的方法
比如:

public abstract void doSome();

抽象类也有构造方法,供子类使用(子类的无参构造第一行有一个隐示super去调用父类的无参构造)

示例程序:

public class Test {
    public static void main(String[] args) {
        A a = new A();//报错,抽象类无法实例化
        B b = new B();//非抽象子类可以实例化
    }
}
abstract class A{
    public abstract void doSome();
    public void doOther(){//抽象类中可以存在非抽象方法

    }
}
class B extends A{
    public void doSome(){//抽象方法在非抽象子类中必须重写

    }
}
abstract class C extends A{//在抽象子类中不需要重写父类抽象方法
}

1.3 接口

1.3.1 接口的基础语法

  • 接口也是一种引用数据类型,接口编译后也是.class字节码文件
  • 接口是完全抽象的(抽象类是半抽象)
  • 接口是可以继承的,并且支持多继承
  • 接口中只能包含常量和抽象方法
  • 接口中所有元素都是公开的,public也可以省略
  • 接口中抽象方法的public abrstact可以省略
  • 接口中常量定义的 public static final可以省略
  • 一个非抽象的类,实现接口时,必须将接口中所有方法实现
  • 一个类可以实现多个接口
  • extends和implements同时出现时,extends写在前,implements写在后
  • 使用接口时,可以使用多态(父类型引用指向子类型对象)

​定义接口的语法格式:

[修饰符列表] interface 接口名{

}

示例程序:

public class Test {
    public static void main(String[] args) {

    }
}
interface A{

}
interface B extends A{

}
interface C extends A,B{

}
interface MyMath{

    //public static final double PI=3.12;
    double PI=3.12;
    //public abstract int sum(int a,int b);
    int sum(int a,int b);
}

接口可以看作是类,类之间叫继承,类和接口之间叫实现通过implements关键字完成
当一个非抽象的类实现接口时,必须将接口中的所有抽象方法全部实现(覆盖重写)
子类的方法访问权限要更封闭才行

示例程序:

public class Test1 {
    public static void main(String[] args) {

    }
}

interface MyMath{
    double PI=3.12;
    int sum(int a,int b);
    int sub(int a,int b);
}
class MyMathImp implements MyMath{//重写的方法访问权限必须更封闭
	public int sum(int a,int b){
	return a+b;
	}    
	public int sub(int a,int b){
		return a-b;
	}    
}
//abstract class MyMathImp implements MyMath{

//}

接口和多态联合使用

示例程序:

public class Test {
    public static void main(String[] args) {
        MyMath mm = new MyMathImp();
        System.out.println(mm.sum(30,10));
        System.out.println(mm.sub(30,10));
    }
}

interface MyMath{
    double PI=3.14;
    int sum(int a,int b);
    int sub(int a,int b);
}
//class MyMathImp implements MyMath{
//
//}
class MyMathImp implements MyMath{
    public int sum(int a,int b){
        return a+b;
    }
    public int sub(int a,int b){
        return a-b;
    }
}

运行结果:

40
20

一个类可以实现多个接口,弥补了类不能多继承的缺点
接口之间在强制类型转换时,没有继承关系也可以强转。但是运行时可能会出现ClassCastException异常(假装当没讲,容易混淆没啥用)

示例程序:

public class Test {
    public static void main(String[] args) {
		A a = new D();
		B b = new D();
		C c = new D();
		
		B b2 = (B)a;//A和B之间没有继承关系
		b2.b();
    }
}

interface A{
    void a();
}
interface B{
    void b();
}
interface C{
    void c();
}
class D implements A,B,C{
    public void a(){

    }
    public void b(){
		System.out.println("b....");
    }
    public void c(){
 
    }
}

运行结果:

b....
public class Test1 {
    public static void main(String[] args) {
        B b = new C();
       if(B instanceof A){
        	A a = (A)b;//如果没有检查,就会报错
	/*Exception in thread "main" java.lang.ClassCastException: class C cannot be cast to class A (C and A are in unnamed module of loader 'app')
	at Test1.main(Test1.java:4)*/
       }
       
    }
}

interface A{

}
interface B{

}
class C implements B{

}

extends和implements同时出现
extends写在前,implements写在后
接口通常提取的时行为动作

示例程序:

public class Test1 {
    public static void main(String[] args) {
       Flyable f = new Cat();
       f.fly();
    }
}
class Animal{

}
interface Flyable{
    void fly();
}
class Cat extends Animal  implements Flyable{
    public void fly(){
        System.out.println("飞猫起飞!");
    }
}

运行结果:

飞猫起飞!

1.3.2 接口在开发中的作用

接口在开发中的作用,类似多态在开发中的作用

示例程序:

public interface FoodMenu {
    void xiHongShijiDan();
    void yuXiangRouSi();
}
public class Customer {
    //凡是可以用has a形容的,统一用属性的方式存在
    //顾客有一个菜单
    private FoodMenu foodMenu;

    public Customer() {
    }
    public Customer(FoodMenu foodMenu) {
        this.foodMenu = foodMenu;
    }

    public FoodMenu getFoodMenu() {
        return foodMenu;
    }

    public void setFoodMenu(FoodMenu foodMenu) {
        this.foodMenu = foodMenu;
    }
    public void order(){
        //FoodMenu fm = this.getFoodMenu();
        foodMenu.xiHongShijiDan();
        foodMenu.yuXiangRouSi();

    }
}
public class ChinaCooker implements FoodMenu{

    public void xiHongShijiDan() {
        System.out.println("西红柿鸡蛋中国味道");
    }
    public void yuXiangRouSi() {
        System.out.println("鱼香肉丝中国味道");
    }
}
public class AmericaCooker implements FoodMenu{
    public void xiHongShijiDan() {
        System.out.println("西红柿鸡蛋美国味道");
    }
    public void yuXiangRouSi() {
        System.out.println("西红柿鸡蛋美国味道");
    }
}
public class Restaurant {
    public static void main(String[] args) {
        FoodMenu cooker1 = new ChinaCooker();
        Customer c1 = new Customer(cooker1);
        c1.order();
    }

}

运行结果:

西红柿鸡蛋中国味道
鱼香肉丝中国味道

1.3.3 类和类之间的关系

is a、has a、 like a

  • is a:Cat is a Animal 表示继承关系
    凡是满足is a的表示继承关系
  • has a:I has a Pen表示关联关系
    关联关系通常以属性形式存在
  • like a:Cooker like a FoodMenu表示实现关系
    实现关系通常是:类实现接口

1.3.4 抽象类和接口的区别

  • 抽象类是半抽象的,接口是完全抽象的
  • 抽象类有构造方法,接口没有构造方法
  • 接口之间支持多继承,类之间只有单继承
  • 一个类可以实现多接口,一个抽象类只能继承一个类
  • 接口中只能出现常量和抽象方法
  • 一般接口使用的比较多,接口一般是对行为的抽象

1.4 包机制

  • package是Java包机制。是为了方便程序的管理,不同功能的类分别存放在不同的包下。
  • package是一个关键字,后面加包名。例如:package com.baidu.javase.chapter17
  • package只允许出现在Java源代码的第一行(注释行不算)
  • 包名一般采用公司域名倒序的方式
    包名命名规范:公司域名倒序+项目名+模块名+功能名

package的Java程序编译和运行:
在chapter17目录下的HelloWorld.java文件
在这里插入图片描述
此时类名已变为com.bjpowernode.javase.chapter17.HelloWorld
编译:
在这里插入图片描述
javac -d . HelloWorld.java
javac负责编译
-d带包编译
. 代表编译之后生成的东西放在当前目录下
HelloWorld.java 被编译的java文件名

运行:
在这里插入图片描述

1.4.1 使用包机制

  • 如果两个程序在同一package下,包名可以省略。不在同一包名下,必须写全包名。
    示例程序:
package com.bjpowernodejavase.chapter17;
public class Test1{
	public static void mian(String[] args){
		com.bjpowernode.javase.chapter17.HelloWorld hw = new com.bjpowernode.javase.chapter17.HelloWorld();
		HelloWorld hw2 = new HelloWorld();//同一包名下,可以省略包名
	}
}
package com;
public class Test2{
	public static void mian(String[] args){
		//Test1在com.bjpowernodejavase.chapter17包下,Test2在com包下,不能省略包名
		com.bjpowernode.javase.chapter17.HelloWorld hw = new com.bjpowernode.javase.chapter17.HelloWorld();
		
	}
}

1.4.2 使用import机制

  • import语句只能出现在package语句之下,class声明语句之上
  • 当两个类不在同一包时,使用import。在同一包内,不需要使用
  • lang包下的东西都不需要手动导,程序自动导

示例程序:

package com;
import com.bjpowernodejavase.chapter17.HelloWorld;//将需要的类导入
public class Test3{
	public static void mian(String[] args){
		HelloWorld hw = new HelloWorld();
	}
}
package com.bjpowernodejavase.chapter17;

public class Test4{
	public static void mian(String[] args){
		java.util.Scanner s = new java.util.Scanner(System.in);//必须写明包
	}
}
package com.bjpowernodejavase.chapter17;
import java.util.Scanner;
public class Test5{
	public static void mian(String[] args){
		//此类和Scanner类不在同一个包
		java.util.Scanner s = new java.util.Scanner(System.in);//必须写明包
	}
}

在Test5中也可以写为:

import java.util.*;//*在此只能代表某些类的名字

此种写法运行速度不会比以上写法慢

1.5访问权限控制符

  • private 私有
  • protected 受保护
  • public 公开

1.5.1 访问控制修饰符的控制范围

  • private 只能在本类中访问
  • protected 只能在本类,同包,子类中访问
  • public 在任何位置都能访问
  • 默认 只能在本类和同包下访问
    范围由大到小:public > protected > 默认 > private

1.5.2 访问控制修饰符修饰的对象

属性(4个都能用)
方法(4个都能用)
类(public和默认可以)
接口(public和默认可以)

1.6 Object类

Object类中的常用方法可以查阅Java类库的帮助文档
API是应用程序编程接口
整个JDK类库就是一个Java SE的API
每一个API都会配置一个API帮助文档
目前需要掌握的几个方法:

protected Object clone()//负责对象克隆
int hashCode()//获取对象哈希值的一个方法
boolean equals(Object obj)//判断两个对象是否相等
String toString()//将对象转换成字符串形式
protected void finalize()//垃圾回收器负责调用的方法

1.6.1 Object类的toString方法

  • toString方法可以将一个Java对象转换成字符串表示形式

示例程序:

public class test2 {
    public static void main(String[] args) {
        MyTime t1 = new MyTime(1970,1,1);
        String s1 = t1.toString();
        System.out.println(s1);
    }
}
class MyTime{
    int year;
    int month;
    int day;
    public MyTime(){

    }
    public MyTime(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
}

运行结果:

MyTime@49e4cb85

但是我们并不期待这样的结果,我们期待的是具体的日期结果,所以最好重写toString()方法。

建议所有子类都重写这个方法

示例程序:

public class test {
    public static void main(String[] args) {
        MyTime t1 = new MyTime(1970,1,1);
        String s1 = t1.toString();
        System.out.println(s1);
    }
}
class MyTime{
    int year;
    int month;
    int day;
    public MyTime(){

    }
    public MyTime(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
   public String toString(){
        return this.year+"年"+this.month+"月"+this.day+"日";
   }
}

运行结果:

1970年1月1日

1.6.2 Object类的equals方法

  • equals方法用来判断两个对象是否相等
  • “==”用来判断两个基本数据类型是否相等,equals用来判断两个引用数据类型是否相等
  • String类重写了equals方法
  • String类重写了toString方法
    equals方法的源代码:
public boolean equals(Object obj){
	return (this == obj);//源代码中用的“==”
}

示例程序:

public class test  {
    public static void main(String[] args) {
        MyTime t1 = new MyTime(1970,1,1);
        MyTime t2 = new MyTime(1970,1,1);
        //判断两个Java对象不能使用“==”
        System.out.println(t1==t2);//此处判断的是t1、t2中保存的对象内存地址是否相等
    
    }
}
class MyTime{
    int year;
    int month;
    int day;
    public MyTime(){

    }
    public MyTime(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
}

运行结果:

false

重写equals方法
示例程序:

public class test {
    public static void main(String[] args) {
        MyTime t1 = new MyTime(1970,1,1);
        MyTime t2 = new MyTime(1970,1,1);

        System.out.println(t1==t2);
        System.out.println(t1.equals(t2));
    }
}
class MyTime{
    int year;
    int month;
    int day;
    public MyTime(){

    }

    public MyTime(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
    public boolean equals(Object obj) {
        if(ibj == null){
			return false;
		}
        //当年月日都相等时,认为两个对象相等
        int year1 = this.year;
        int month1 = this.month;
        int day1 = this.day;
		//想要访问子类中特有的东西
		if(obj instance MyTime){
			return false;
		}
       //向下转型 强转
            MyTime mt = (MyTime) obj;
            int year2 = mt.year;
            int month2 = mt.month;
            int day2 = mt.day;
            if(this.year == year2&&this.month == month2&&this.day == day2){
                return true;
            }
            return false;
       
    }
}

运行结果:

false
true

比较两个字符串必须用equals方法

示例程序:

public class test {
    public static void main(String[] args) {
        String s1 = "Hello";
        String s2 = "Hello";
        String s3 = new String("Hello");
        String s4 = new String("Hello");
        System.out.println(s1==s2);
        System.out.println(s1.equals(s2));
        System.out.println(s3==s4);
        System.out.println(s3.equals(s4));
    }
}

运行结果:

true
true
false
true

String类重写了toString方法

示例程序:

public class test {
    public static void main(String[] args) {
        String x = new String("Hello");
        System.out.println(x);//引用数据类型当不写toString方法时,自动调用toString方法
        System.out.println(x.toString());//如果没重写toString,结果应为String@十六进制的地址
    }
}

运行结果:

Hello
Hello

示例程序:

public class test2 {
    public static void main(String[] args) {
        Student s1 = new Student(111,"北京");
        Student s2 = new Student(112,"北京");
        System.out.println(s1 == s2);//false
        System.out.println(s1.equals(s2));//true

//        Student s3 = new Student(111,new String("北京"));
//        Student s4 = new Student(112,new String("北京"));//两个北京的内存地址不同,如果用equals比较那两者通用
//        System.out.println(s3 == s4);//false
//        System.out.println(s3.equals(s4));//false
    }
}
class Student{
    int no;
    String school;
    public Student() {
    }

    public Student(int no, String school) {
        this.no = no;
        this.school = school;
    }

    public String toString() {
        return "学号"+no+"学校名称"+school;
    }
    public boolean equals(Object obj) {
        if(obj == null||!(obj instanceof Student)) return false;
        if(this == obj) return true;
        Student s = (Student) obj;
        return this.no == s.no && this.school.equals(s.school);
        //return this.no == s.no && this.school == s.school);//不可以
    }
}

运行结果:

false
false

equals方法的深层次理解
重写equals方法要彻底
示例程序:

public class test {
    public static void main(String[] args) {
        Address addr1 = new Address("北京","海淀区","111");
        User u1 = new User("张三",addr1);
        // User u1 = new User("张三", new Address("北京","海淀区","111"));
        User u2 = new User("张三", new Address("北京","海淀区","111"));
        System.out.println(u1.equals(u2));//true
    }
}
class User{
    String name;
    Address addr;
    public User() {
    }
    public User(String name, Address addr) {
        this.name = name;
        this.addr = addr;
    }
    //重写equals方法
    //当一个用户的姓名和地址都相同时,表示是同一个用户。这里判断两个User对象是否相等
    public boolean equals(Object obj) {
       if(obj == null||!(obj instanceof User)) return false;
       if(this == obj) return true;
        User u = (User)obj;
       if(this.name.equals(u.name) && this.addr.equals(u.addr)){
            return true;
       }
       return false;
    }
}
class Address{
    String city;
    String street;
    String zipcode;
    public Address() {
    }
    public Address(String city, String street, String zipcode) {
        this.city = city;
        this.street = street;
        this.zipcode = zipcode;
    }
    //这里不重写equals方法会导致上面的条件里addr的equals比较的是内存地址
    public boolean equals(Object obj) {
        if(obj == null||!(obj instanceof Address)) return false;
        if(this == obj) return true;
        Address a = (Address)obj;
        if(this.city.equals(a.city) && this.street.equals(a.street) && this.zipcode.equals(a.zipcode)){
            return true;
        }
        return false;
    }
}

运行结果:

true

1.6.3 Object类的finalize方法(了解即可,已过时)

JDK9之后就没有这个方法了
在Object类中的源代码:
protected void finalize() throws Throwable{}
只有一个方法体
finalize()方法是被protected修饰的
不需要手动调用,JVM的垃圾回收器自动调用这个方法,我们只需要重写这个方法,之后会有GC来调用
当一个对象即将被垃圾回收器回收时,调用
finalize是一个垃圾销毁时机,如果希望在对象即将被销毁时执行一段代码,这段代码写在finalize方法中
示例程序:

public class test {
    public static void main(String[] args) {
     for (int i=0;i<1000000;i++){
         Person p = new Person();
         //将p变成垃圾
         p = null;
     }
    }
}
class Person{
    //重写finalize方法
    //Person类的对象被垃圾回收器回收时,垃圾回收器负责调用p.finalize();
    protected void finalize() throws Throwable {
        System.out.println("即将被销毁");
    }
}

垃圾回收器不是轻易启动的,垃圾太少或者时机未到等条件下可能启动可能不启动

system.gc();//建议gc启动,可能听,也可能不听

1.6.4 Object类的hashCode方法

hashCode的源代码:
public native int hashCode();
这个方法带有native关键字,底层调用了C++程序
hashCode()方法返回的是哈希码:
实际上就是一个内存地址,经过哈希算法得到一个值
示例程序:

public class test {
    public static void main(String[] args) {
        Object o = new Object();
        int hashCode = o.hashCode();
        System.out.println(hashCode);
    }
}

运行结果:

2083562754

1.7 匿名内部类

内部类:在类的内部又定义了一个新的类
内部类分为:静态内部类、实力内部类、局部内部类

示例程序:

class Test{
    static class Inner1{//静态内部类
        
    }
    class Inner2{//实例内部类

    }
    public void doSome(){
        int i = 100;//局部变量
        class Inner3{//局部内部类
			
		}
    }
    public void doOther(){
		//doSome()中的局部内部类Inner3,在doOther()中不能用
    }
}

匿名内部类是局部内部类的一种,此类没有名字

未使用匿名内部类
示例程序:

public class test2 {
    public static void main(String[] args) {
        MyMath mm = new MyMath();
        mm.MySum(new ComputerImp(),100,200);
    }
}
interface Computer{
    //抽象方法
    int sum(int a,int b);
}
class ComputerImp implements Computer{//接口的实现类
    public int sum(int a, int b) {
        return a + b;
    }
}
class MyMath{
    public void MySum(Computer c,int a,int b){
        int retValue = c.sum(a,b);
        System.out.println(a+"+"+b+"="+retValue);
    }
}

使用匿名内部类,可以不写接口的实现类

示例程序:

public class test2 {
    public static void main(String[] args) {
        MyMath mm = new MyMath();
        mm.MySum(new Computer(){
            public int sum(int a,int b){
                return a + b;
            }
        },100,200);
    }
}
interface Computer{
    //抽象方法
    int sum(int a,int b);
}
class MyMath{
    public void MySum(Computer c,int a,int b){
        int retValue = c.sum(a,b);
        System.out.println(a+"+"+b+"="+retValue);
    }
}

二、数组

  • Java中数组是一种引用类型,数组的父类是Object类
  • 数组是一个容器,可以同时容纳多个容器(数组是一个数据的集合)
  • 数组中可以存基本数据类型,也可以存引用数据类型
  • 数组是引用数据类型,所以数组对象是在堆内存中
  • 数组中存储的是Java对象的话,实际上存储的是对象的引用(内存地址),不能直接存储Java对象
  • 在Java中,数组一旦创建,长度不可变
  • 数组分为一维数组、二维数组、三维数组、多维数组…
  • 所有数组对象都有length属性(Java自带),用来获取数组中元素的个数
  • Java中要求数组的元素类型统一:int类型只能装int类型元素
  • 数组在内存方面存储时,数组中的元素内存地址是连续的
  • 数组中首元素的内存地址当作整个数组的内存地址
  • 数组中每一个元素都是由下标的,从0开始,最后一个元素的下标是length-1
  • 对数组元素进行存取时,都需要通过下标

数组的数据结构的优缺点:
优点:

每一个元素的内存地址在空间上是连续的
每一个元素类型相同,占用空间大小一样
知道第一个元素的内存地址,知道每一个元素的占用空间,也知道下标,所以可以通过数学表达式计算出某个下标上元素的内存地址,直接通过内存地址定位元素,所以数组的检索效率最高
数组存储100个和一万个元素在元素查询和检索方面效率是相同的,数组在元素查找时不会一个一个的找,而是通过数学表达式直接算出来的

缺点:

为了保证数组每个元素内存地址的连续性,所以在数组上随机增删元素的时候,效率较低,因为随即增删元素时会涉及到后面的元素同意向前或者向后位移的操作
数据不能存储大数据量,因为很难在内存中找到一块特别大的连续的内存空间
对于数组最后一个元素的增删,是没有效率影响的

2.1一维数组的声明和初始化

一维数组的声明语法格式:

数据类型[] array;
int[] i;
String[] str;

初始化数组有两种方法:
静态初始化语法格式:

int[] array = {100,200,300};

动态初始化语法格式:

int[] a = new int[5];//初始化一个长度为5的int类型数组,每个元素为默认值0;
String[] str = new String[6];//初始化长度为6的String类型数组,每个元素为默认值null 

对一维数组元素的访问

示例程序:

public class test {
    public static void main(String[] args) {
        int[] a = {1,100,10,20,55,689};
        System.out.println("数组中元素个数"+a.length);
        System.out.println("第一个元素"+a[0]);
        System.out.println("最后一个元素"+a[5]);
        System.out.println("最后一个元素"+a[a.length - 1]);
        //修改第一个元素为111;
        a[0] = 111;
        //修改最后一个元素为0;
        a[a.length - 1] = 0;
        System.out.println("第一个元素"+a[0]);
        System.out.println("最后一个元素"+a[a.length - 1]);
    }
}

运行结果:

数组中元素个数6
第一个元素1
最后一个元素689
最后一个元素689
第一个元素111
最后一个元素0

一维数组的遍历:

public class test {
    public static void main(String[] args) {
        int[] a = {1,100,10,20,55,689};
        for (int i=0;i< a.length;i++){//遍历数组
            System.out.println("顺序输出"+a[i]);
        }
        //System.out.println(a[6]);//Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 6 out of bounds for length 6at test2.main(test2.java:7)
        for (int i = a.length - 1;i >= 0;i--){//反向遍历数组
            System.out.println("倒序输出"+a[i]);
        }
    }
}

运行结果:

顺序输出1
顺序输出100
顺序输出10
顺序输出20
顺序输出55
顺序输出689
倒序输出689
倒序输出55
倒序输出20
倒序输出10
倒序输出100
倒序输出1

动态初始化一维数组

示例程序:

public class test {
    public static void main(String[] args) {
        int[] a = new int[6];
        for (int i=0;i< a.length;i++){
            System.out.println("第"+i+"个元素:"+a[i]);
        }
    }
}

运行结果:

第0个元素:0
第1个元素:0
第2个元素:0
第3个元素:0
第4个元素:0
第5个元素:0

当创建数组时,不确定数组中存储哪些数据,用动态初始化方式

方法的参数是数组:

public class test {
    public static void main(String[] args) {
        int[] a = {1,2,3,4,5};
        printArray(a);
        String[] str = {"Hello","World","Huawei","harmony"};
        printArray(str);
        String[] str1 = new String[3];
        printArray(str1);
        printArray(new int[]{1,2,3});//直接传一个静态数组进去,括号里为空
    }
    public static void printArray(int[] array){
        for (int i = 0;i< array.length;i++){
            System.out.println(array[i]);
        }
    }
    public static void printArray(String[] array){
        for (int i = 0;i< array.length;i++){
            System.out.println(array[i]);
        }
    }
}


运行结果:

1
2
3
4
5
Hello
World
Huawei
harmony
null
null
null
1
2
3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Spring伦儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值