Java基础
2024-06-10 18:30:07 13 举报
AI智能生成
Java基础是Java编程语言的核心内容,涵盖了变量、数据类型、运算符、条件语句、循环结构、数组、函数、类、对象和异常处理等方面的知识。Java文件通常以.java为扩展名,且需要经过编译和运行两个步骤。Java语言具有跨平台、面向对象、分布式、多线程、安全等特点,被广泛应用于web开发、移动应用开发、大数据处理和科学计算等领域。
作者其他创作
大纲/内容
面向对象编程(基础部分)
类与对象
类和对象的区别和联系
- 类是抽象的,概念的,代表一类事物,它是一种数据类型。
- 对象是具体的,实际的,代表一个具体事物。
- 类是对象的模板,对象是类的一个个体,对应一个实例。
对象在内存中的存在形式
注意细节:
- 创建对象,首先将Cat类信息(属性和方法信息,只会加载一次)加载到方法区。
- 然后在堆中分配空间,进行默认初始化,如属性类型为int 是0。
- 继而把地址赋给cat(对象引用),cat会指向对象。
- 最后进行指定初始化,即对属性进行赋值(根据类型,决定是否开辟空间..)。
java内存的结构分析
栈:一般存放基本数据类型(局部变量)
堆:存放对象(Cat cat,数组等)
方法区:常量池(常量,比如字符串),类加载信息
栈:一般存放基本数据类型(局部变量)
堆:存放对象(Cat cat,数组等)
方法区:常量池(常量,比如字符串),类加载信息
类与对象
属性(成员变量)
基本介绍:
概念或者叫法上,成员变量、属性,field都可以。
属性是类的一个组成部分,一般是基本数据类型,当然也可以是引用类型,如对象,数组。
概念或者叫法上,成员变量、属性,field都可以。
属性是类的一个组成部分,一般是基本数据类型,当然也可以是引用类型,如对象,数组。
注意事项和细节
- 属性的定义语法同变量:访问修饰符 属性类型 属性名;
- 属性的定义类型可以为任意类型,包含基本类型和引用类型;
- 属性如果不赋值,有默认值,规则和数组一致。
如何创建对象
先声明,在创建。
直接创建。
Cat cat=new Cat();
Cat cat=new Cat();
如何访问属性
基本语法:对象名.属性名;
成员方法
方法引入及调用机制分析
成员方法的功能【为什么要有方法】:
- 提高代码的复用性。
- 可以将实现的细节封装起来,然后供其他用户调用即可。
方法定义:
- 形参列表:表示成员方法输入。
- 返回数据类型:表示成员方法输出,void表示没有返回值。
- 方法主体:表示为了实现某一功能代码快。
- return: 有返回值时,必须有。没有返回值时,可以有,但后面不能加返回值,如return ;(此时没有意思,一般省略)
注意事项和使用细节
- 一个方法只有一个返回值。
- 返回类型可为任意类型,基本类型,引用类型都可以。
- 有返回数据时,必须有return,返回值类型必须一致或兼容。
- 方法名:建议驼峰法,见名知意。
- 方法是有修饰符的,用来表明方法可供使用的范围,共4种(后面细讲)
- 使用方法时,形参和实参,保持一致,类型一致或兼容,个数,顺序必须一致。
- 方法体内不能在定义方法,即不能嵌套定义。方法内可以进行方法调用。
方法的调用:
- 同类方法,直接调用。
- 不同类方法,对象名调用。跨类的方法调用还与方法的修饰符有关,后面详讲。
成员方法传参机制
基本类型数据,传递的是值(值拷贝),形参的任何改变不影响实参。
引用数据类型,传递的是引用(也可以说是值,这个值是地址),可以通过形参影响实参。
递归
基本介绍:
简单的说:递归就是方法自己调用自己,每次调用时传入不同的变量。递归有助于编程者解决复杂问题,同时可以让代码变得简洁。
简单的说:递归就是方法自己调用自己,每次调用时传入不同的变量。递归有助于编程者解决复杂问题,同时可以让代码变得简洁。
递归能够解决的问题
递归在内存中的运行机制
递归重要规则:
- 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
- 方法的局部变量是独立的,不会相互影响,前提是基本数据类型。如果是引用类型比如数组、对象,就会共享该引用类型的数据。
- 递归必须向退出递归的条件逼近,否则就会无限递归,出现stackOverflowError.
- 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用就将结果返回给谁。
经典案例:阶乘、斐波那契数列、老鼠出迷宫(二维数组,递归)、汉诺塔、八皇后
这几个案例,由浅入深,尤其是老鼠出迷宫后3个,还是可以深入研究一下的。
这几个案例,由浅入深,尤其是老鼠出迷宫后3个,还是可以深入研究一下的。
重载(overload)
基本介绍:
java中允许同一类中,多个同名方法的存在,但要求形参列表不一致。
好处:减轻了起名、记名的麻烦。
java中允许同一类中,多个同名方法的存在,但要求形参列表不一致。
好处:减轻了起名、记名的麻烦。
注意事项和使用细节:
- 方法名:必须相同。
- 参数列表:必须不同(参数类型或个数或顺序,至少有一样不同,参数名无要求)。
- 返回类型:无要求。
可变参数
基本概念:
java允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。
java允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。
基本语法:
访问修饰符 返回类型 方法名(数据类型... 形参名){}
访问修饰符 返回类型 方法名(数据类型... 形参名){}
注意事项和使用细节:
- 可变参数的实参可以为0或任意多个。
- 可变参数的实参可以为数组,它的本质就是数组。
- 一个形参列表中只能出现一个可变参数,且必须在参数的最后一个(可变参数可以和普通类型的参数一起放在形参列表)。
作用域
基本使用:(变量作用域)
java编程中,主要的变量就是属性(成员变量)和局部变量(一般是指成员方法中定义的变量)。
作用域的分类:
全局变量:也就是属性,作用域为整个类体。
局部变量:除了属性之外的其它变量,作用域为定义它的代码块中。
全局变量可以不赋值,直接使用,因为有默认值,局部变量必须赋值后,才能使用,因为没有默认值。
java编程中,主要的变量就是属性(成员变量)和局部变量(一般是指成员方法中定义的变量)。
作用域的分类:
全局变量:也就是属性,作用域为整个类体。
局部变量:除了属性之外的其它变量,作用域为定义它的代码块中。
全局变量可以不赋值,直接使用,因为有默认值,局部变量必须赋值后,才能使用,因为没有默认值。
作用域:注意事项和细节使用
- 属性和局部变量可以重名,访问时遵循就近原则。
- 在同一个作用域中,比如同一个成员方法中,两个局部变量,不能重名。
- 属性生命周期较长,伴随着对象的创建而创建,伴随着对象的死亡而死亡。局部变量,生命周期较短,伴随它的代码块的执行而创建,伴随着方法的结束而死亡,即用在一次方法调用过程中。
- 作用域不同:全局变量,可以被本类使用,或其它类使用(通过对象调用)局部变量,只能在本类中对应的方法的使用。
- 修饰符不同:全局变量【属性】可以加修饰符。局部变量不可以加修饰符。
构造器
基本介绍:
构造方法又叫构造器,是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。
特点:
方法名和类名相同。
没有返回值。
在创建对象时,系统会自动的调用该类的构造器完成对象的初始化。
构造方法又叫构造器,是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。
特点:
方法名和类名相同。
没有返回值。
在创建对象时,系统会自动的调用该类的构造器完成对象的初始化。
基本语法:修饰符 方法名(形参列表){方法体;}
- 构造器的修饰符可以默认;
- 构造器没有返回值;
- 方法名和类名字必须一样;
- 参数列表和成员方法一样的规则;
- 构造器的调用由系统完成。
注意事项和使用细节:
- 一个类可以定义多个不同的构造器,即构造器重载。
- 构造器是完成对象的初始化,而不是创建对象。
- 如果没有定义构造方法,系统会自动生成一个默认无参构造方法。可通过javapz指令反编译.class文件查看。一旦定义之后,就不会有默认的无参构造方法了,如果想使用,需要手动添加。
javap 了解,javap hello.class 可以查看源码。如果想查看其他信息,可添加相关指令,如-c,-v等。
对象创建初始化流程分析
加载person类信息(Person.class),只会加载一次。 在堆中分配空间(地址)。 完成对象初始化1默认初始化age=0 name=null 2显示初始化 age=90 name=null 3构造器初始化 age=20,name=小倩 将对象在堆中的地址,返回给p(p是对象名,也可以理解为对象引用。)
心得:看到这部分,这些设计的东西,是有一定规律或者说法的,不是想当然来的。比如,默认一个无参构造,是为了满足基础的对象创建,如果定义了新的构造方法,自然不需要默认定义(可有可无)。 在无参构造的语法设计上,没有返回值,且不需要写void,这样只通过此处,就能给普通方法区分。 再加上与类名相同,这样系统调用构造器的时候,可以直接匹配上对应构造器。 构造器通过重载,来满足多种需要。 很巧妙。
this
什么是this?
java虚拟机会给每个对象分配this,代表当前对象。
主要解决问题:
使用this解决构造器中变量命名问题。
java虚拟机会给每个对象分配this,代表当前对象。
主要解决问题:
使用this解决构造器中变量命名问题。
感觉图上画的有些乱,可以认为this是堆中对象的一个属性即可。相比于生活中我的用法。
this关键字的注意事项和使用细节
- this关键字可以用来访问本类的属性、方法、构造器。
- this用于区分当前类的属性和局部变量。
- 访问成员方法的语法:this.方法名(参数列表);
- 访问构造器语法:this(参数列表);注意只能在构造器中使用,且放在第一行。
- this不能在类定义的外部使用,只能在类定义的方法中使用。
习题思考:用Double作返回数据类型,可以接收null。解决double接受返回值的局限性。
面向对象编程(中级部分)
IDEA
IDEA介绍:
- 全称intellij Idea
- 业界被公认最好的Java开发工具
- 是jetBrains公司的产品,该公司总部位于捷克的首都布拉格
- 除了支持java,还支持html,css,php,mysql,python
ide(集成开发环境)其他工具-eclipse
- eclipse是一个开放源代码的,基于java的可扩展开发平台。
- 最初由ibm公司耗资3000万美金开发的下一代ide开发环境。
- 2001年11月贡献给开源社区。
- 是目前最优秀的java开发ide之一。
下载、安装
背景、字体设置等。
常用快捷键,可自定义键。settings->keymap
- 删除当前行,复制当前行,补全代码,取消注释,自动导入类,快速格式化,快速运行,快速生成构造方法等。
- 查看类层级关系: ctrl+h;
- 查看方法: ctrl+b;
自定义模板:
file->settings->editor->live templates->
file->settings->editor->live templates->
常用插件
codota代码智能提示插件
打出首字母就能联想出一整条语句,还显示了每条语句的使用频率。
key promoter x快键键提示插件
每次都会在右下角弹窗提示,帮助快速熟悉快捷键。
codeglance 显示代码缩略图插件
lombok 简化臃肿代码插件
alibaba java coding guidelines 阿里巴巴代码规范检查插件
sonarlint代码质量检查插件
包
三大作用:
- 区分相同名字的类。
- 当类很多时,方便管理。如api文档。
- 控制访问范围。
基本语法:package com.bear;
pachage 关键字,表示打包。
com.bear 包名。
pachage 关键字,表示打包。
com.bear 包名。
包的本质:
创建不同的文件夹来保存类文件。
创建不同的文件夹来保存类文件。
包的命名
命名规则:数字、字母、下划线,数字不能开头,不能是关键字或保留字。
命名规范:一般是小写,公司名、项目名、业务模块名;
命名规则:数字、字母、下划线,数字不能开头,不能是关键字或保留字。
命名规范:一般是小写,公司名、项目名、业务模块名;
常用包:
java.lang.* 基础包,默认引用。
java.util.* 工具包,如scanner。
java.net.* 网络包。
java.awt.* 界面开发包,GUI。
java.lang.* 基础包,默认引用。
java.util.* 工具包,如scanner。
java.net.* 网络包。
java.awt.* 界面开发包,GUI。
注意事项和使用细节:
- package的作用是声明当前类所在的包,需要放在类的最上面,一个类中最多只有一句package;
- import指令 位置放在package的下面,在类定义前面,可以有多句且没有顺序要求。
访问修饰符
基本介绍:
java提供四中访问控制修饰符号,用来修饰控制方法和属性(成员变量)的访问控制权限。
java提供四中访问控制修饰符号,用来修饰控制方法和属性(成员变量)的访问控制权限。
- 公开级别:public 修饰,对外公开。
- 受保护级别:用protected修饰,对子类和同一包中的类公开。
- 默认级别:没有修饰符号,向同一个包的类公开。
- 私有级别:用private修饰,只有类本身可以访问,不对外公开。
使用注意事项:
- 修饰符可以用来修饰类中的方法和属性,还可以修饰类(不过只有默认和public两种,遵循上面访问特点)。
- 方法的访问规则和属性完全一样。
封装
基本介绍:
封装就是把抽象出来的数据【属性】和对数据的操作【方法】封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作【方法】,才能对数据进行操作。
封装就是把抽象出来的数据【属性】和对数据的操作【方法】封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作【方法】,才能对数据进行操作。
封装的理解和好处
- 隐藏实现细节。
- 可以对数据进行验证,保证安全合理。
封装的实现步骤:
将属性进行私有化private[不能直接修改属性]
提供一个公共的set方法,用于对属性判断并赋值
public void setXxx(类型 参数名){
//加入数据验证的业务逻辑
属性=参数名;
}
提供一个公共的get方法,用于获取属性的值
public XX getXxx(){
return xx;
}
将属性进行私有化private[不能直接修改属性]
提供一个公共的set方法,用于对属性判断并赋值
public void setXxx(类型 参数名){
//加入数据验证的业务逻辑
属性=参数名;
}
提供一个公共的get方法,用于获取属性的值
public XX getXxx(){
return xx;
}
继承
继承基本介绍
继承可以解决代码复用,让我们的编程更加接近人类思维。当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。
继承可以解决代码复用,让我们的编程更加接近人类思维。当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。
继承的基本语法
class 子类 extends 父类{}
class 子类 extends 父类{}
- 子类就会自动拥有父类定义的属性和方法。
- 父类又叫超类,基类。
- 子类又叫派生类。
使用细节:
- 子类继承了所有的属性和方法,在子类中私有属性是不能直接访问的,可以通过公共的方法去访问。
- 子类必须调用父类的构造器,完成父类的初始化。
- 当创建子类对象时,不管使用子类的哪一个构造器,默认情况下总是会调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super显示的去指定使用父类的哪一个构造器完成父类的初始化工作,否则编译器不会通过。
- 如果希望指定调用父类的哪一个构造器 ,可显示调用。
- super使用时,需要构造器第一行。
- super和this都只能放在构造器第一行,因此这两个方法不能共存在一个构造器中。
- java所有类都是object的子类,object是所有类的基类。
- 父类构造器的调用不限制于直接父类,将一直往上追溯到object类。
- 子类最多只能继承一个父类(直接继承),即java中是单继承机制。
- 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系。
super关键字
基本介绍:super代表父类的引用,用于访问父类的属性、方法、构造器。
基本语法:
访问父类的属性,方法,都不能访问带有private修饰。用super.调用。
访问父类构造器:只能放在构造器的第一句,且只能有一句。
访问父类的属性,方法,都不能访问带有private修饰。用super.调用。
访问父类构造器:只能放在构造器的第一句,且只能有一句。
使用的好处与细节
好处:分工明确,父类属性由父类初始化,子类属性由子类初始化。
当子类和父类的成员(属性和方法)重名时,为了访问父类的成员,必须使用super。如果没有重名,使用super,this,直接访问效果是一样的(这是针对访问的成员在父类中)。
super方法不限定直接父类,间接父类也可以。遵循就近原则:A->B->C
好处:分工明确,父类属性由父类初始化,子类属性由子类初始化。
当子类和父类的成员(属性和方法)重名时,为了访问父类的成员,必须使用super。如果没有重名,使用super,this,直接访问效果是一样的(这是针对访问的成员在父类中)。
super方法不限定直接父类,间接父类也可以。遵循就近原则:A->B->C
super与this
方法重写【覆盖】
基本介绍:简单说,方法重写就是子类有一个方法,和父类(包含间接父类)的某个方法(名称,返回类型,参数)一样,那么就说这个子类的方法重写了父类的方法。
注意事项和细节:
- 子类的方法的参数、方法名称,和父类完全一样。
- 子类的返回类型与父类一样,或者是父类返回类型的子类。
- 子类方法不能缩小父类方法的访问权限。
方法重写与重载的对比
多态
多态基本介绍
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础上的。
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础上的。
多态的具体体现
方法的多态:重写和重载的体现。
对象的多态:
一个对象的编译类型和运行类型可以不一致,编译类型在定义对象时就确定了,运行类型是可以变化的(在运行时确定)。编译看左边,运行看右边。 Animal animal= new Dog();
一个对象的编译类型和运行类型可以不一致,编译类型在定义对象时就确定了,运行类型是可以变化的(在运行时确定)。编译看左边,运行看右边。 Animal animal= new Dog();
多态注意事项和细节
多态的前提:两个对象存在继承关系。
多态的前提:两个对象存在继承关系。
多态的向上转型:
不能调用子类中的特有成员(在编译阶段能调用哪些成员,是由编译类型来决定的)。
最终运行效果看子类的具体实现!
- 本质:父类的引用指向了子类的对象。
- 语法:父类类型 引用名= new 子类类型();
- 特点:编译类型看左边,运行类型看右边。
不能调用子类中的特有成员(在编译阶段能调用哪些成员,是由编译类型来决定的)。
最终运行效果看子类的具体实现!
多态的向下转型:
- 语法:子类类型 引用名=(子类类型)父类引用。
- 只能强转父类的引用,不能强转父类的对象。
- 要求父类的引用必须指向的是当前目标类型的对象(把Dog强转给Animal,不能用Cat接收)。
- 可以调用子类类型中的所有成员(满足编译阶段调用成员的原则)。
属性没有重写直说,属性的值看编译类型。
instanceOf比较操作符,用于判断对象的运行类型是否为xx类型或是其子类型。
动态绑定机制
- 当调用对象的方法时,该方法会和对象的内存地址【运行类型】绑定。
- 当调用对象的属性时,没有动态绑定机制,哪里声明,哪里使用。
Object类详解
equals方法:==和equals的对比
- ==:既可以判断基本类型,又可以判断引用类型。
- ==:如果判断基本类型,判断的是值是否相等。如int。
- ==:如果判断引用类型,判断的是地址是否相等,即判断是不是同一个对象。
- equals:是object类中的方法,只能判断引用类型。
- 默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等。比如Integer(已重写),String。
hashCode方法
- 提高具有哈希结构的容器的效率。
- 两个引用,如果指向是同一个对象,哈希值肯定是一样的。
- 两个引用,如果指向的是不同对象,则哈希值是不一样的。
- 哈希值主要是根据地址号来的,但是不能完全将哈希值等价于地址。
toString方法
基本介绍 默认返回:全类名+@+哈希值的十六进制(查看object类的toString方法)。
子类往往重写toString方法,用于返回对象的属相信息。
当直接输出一个对象时,toString方法会被默认的调用。
基本介绍 默认返回:全类名+@+哈希值的十六进制(查看object类的toString方法)。
子类往往重写toString方法,用于返回对象的属相信息。
当直接输出一个对象时,toString方法会被默认的调用。
finalize方法
- 当对象被回收时,系统自动调用该对象的finalize方法。子类可以重写该方法,做一些释放资源的操作。
- 什么时候被回收:当某个对象没有任何引用时,则jvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize方法。
- 垃圾回收机制的调用,是由系统来决定(即它有自己的GC算法),也可以通过System.gc()主动出发垃圾回收机制。
debug
断点调试介绍:在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后可以一步步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。进行分析从而找到这个bug.
提示:在断点调试过程中,是运行状态,是以对象的运行类型来执行的。
断点调试能帮助查看java底层源代码的执行过程,提高java水平。
断点调试能帮助查看java底层源代码的执行过程,提高java水平。
常用快捷键:
- F7跳入,跳入方法内
- F8跳过,逐行执行代码
- shift+F8跳出方法
- F9resume,执行到下一个断点
将光标放到某个变量上,可以看到最新的数据。
断点可以在debug过程中,动态的下断点。
进入jdk源码的方法
面向对象编程(高级)
类变量
static变量保存:
- 在class实例的尾部。class对象在堆中。所以static变量在堆中。
- jdk7以上版本,静态域存储于定义类型的class对象中,class对象如同堆中其他对象一样,
存在于gc堆中。(有说法静态域在方法区中..jdk版本有关系)
共识:
- static变量是同一类所有对象共享。
- static类变量,在类加载的时候就生成了。
什么是类变量
类变量也叫静态变量【静态属性】,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。
类变量也叫静态变量【静态属性】,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。
如何定义类变量
定义语法: 访问修饰符 static 数据类型 变量名;
访问修饰符和static位置可以互换。
定义语法: 访问修饰符 static 数据类型 变量名;
访问修饰符和static位置可以互换。
如何访问类变量
类名.类变量名(推荐)
对象名.类变量名
注意:静态变量的访问修饰符权限和普通一样。
类名.类变量名(推荐)
对象名.类变量名
注意:静态变量的访问修饰符权限和普通一样。
使用注意事项和细节讨论
什么时候需要用到类变量
当我们需要让某个类的所有对象都共享一个变量时,就可以考虑使用类变量(静态变量);
当我们需要让某个类的所有对象都共享一个变量时,就可以考虑使用类变量(静态变量);
类变量与实例变量【普通属性】区别
类变量是该类的所有对象共享的,而实例变量是每个对象独享的。
类变量是该类的所有对象共享的,而实例变量是每个对象独享的。
加上static称为类变量【静态变量】,没有就是实例变量【普通变量,非静态变量】
类变量可以通过类名.类变量名(推荐)或者对象名.类变量名来访问(满足访问权限和范围)
实例变量不能通过 类名.类变量名方式访问。
类变量在类加载时就初始化了,也就是说,即使没有创建对象,只要类加载了,就可以使用类变量了。
类变量的声明周期是随类的加载开始,随着类消亡而销毁。
类方法
类方法基本介绍
类方法也叫静态方法。
访问修饰符 static 数据返回类型 方法名(){}推荐
static 访问修饰符 数据返回类型 方法名(){}
类方法也叫静态方法。
访问修饰符 static 数据返回类型 方法名(){}推荐
static 访问修饰符 数据返回类型 方法名(){}
类方法调用:
类名.类方法名或者对象名.类方法名(满足修饰符访问权限)
类名.类方法名或者对象名.类方法名(满足修饰符访问权限)
使用场景:
当方法中不涉及到任何和对象相关的成员,则可以讲方法设计成静态方法,提高开发效率。
常见:工具类中的方法。
当方法中不涉及到任何和对象相关的成员,则可以讲方法设计成静态方法,提高开发效率。
常见:工具类中的方法。
注意事项和细节讨论
- 类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法去:类方法中无this的参数 普通方法中隐含着this的参数。
- 类方法可以通过类名调用,也可以通过对象名调用。
- 普通方法和对象有关,需要通过对象名调用,不能通过类名调用。
- 类方法中不允许使用和对象有关的关键字,比如this和super。普通方法都可以。
- 类方法【静态方法】中只能访问静态变量或静态方法。
- 普通成员方法,既可以访问普通变量(方法)也可以访问静态变量(方法)。
main方法
深入理解main方法
- main方法是虚拟机调用。
- java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public。
- java虚拟机在运行main方法时不必创建对象,所以该方法必须是static。
- 该方法接收string类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数。
- java hello第一个参数,第二个参数 (在main方法中,打印args,可打印参数值。hello是类名)
特别提示:
在main()方法中,我们可以直接调用main方法所在类的静态方法或静态属性。
但是不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,
才能通过这个对象去访问类中的非静态成员。
在main()方法中,我们可以直接调用main方法所在类的静态方法或静态属性。
但是不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,
才能通过这个对象去访问类中的非静态成员。
代码块
基本介绍
代码化块又称为初始化块,属于类中的成员(即类的一部分),类似于方法,将逻辑语句封装在方法体中,通过{}包围起来,但是和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显示调用,而是加载类时,或创建对象时隐式调用。
代码化块又称为初始化块,属于类中的成员(即类的一部分),类似于方法,将逻辑语句封装在方法体中,通过{}包围起来,但是和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显示调用,而是加载类时,或创建对象时隐式调用。
基本语法[修饰符]{代码};
- 修饰符,可选,写或不写,写的话,只能写static。
- 代码块分为两类,使用static修饰的叫静态代码块,没有static修饰的,叫普通代码块。
- 逻辑语句可以为任意逻辑语句(输入,输出,方法调用,循环,判断等)
- ;号可以写上,也可以省略。
注意事项和细节讨论
注意事项和细节讨论
- static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次。
- 类什么时候被加载? 1、创建对象实例。 2、创建子类对象实例。 3、使用类的静态成员(静态属性、静态方法)时。
- 普通的代码块,在创建对象实例时,会被隐式的调用,被创建一次,调用一次。如果是使用类的静态成员时,普通代码块并不会执行。
4.创建一个对象时,在一个类中调用顺序是:
- 调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态属性初始化,则按它们定义的顺序调用)。
- 调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按它们定义的顺序调用)。
- 调用构造方法。
5.构造方法(构造器)的最前面其实隐含了super()和调用普通代码块。静态相关的代码块,属性初始化,在类加载时,就执行完毕,因此是优先于构造器和普通代码块执行的。
6.创建一个子类时,它们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如:
- 父类的静态代码块和静态属性(优先级一样,按定义顺序执行)。
- 子类的静态代码块和静态属性(优先级一样,按定义顺序执行)。
- 父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)。
- 父类的构造方法。
- 子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)。
- 子类的构造方法。
7.静态代码块只能调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员。
static在设计模式中应用
什么是设计模式?
- 静态方法和属性的经典使用。
- 设计模式是在大量的时间中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。
什么是单列模式(单个的实例)
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
单例模式有两种方式:1)饿汉式 2)懒汉式
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
单例模式有两种方式:1)饿汉式 2)懒汉式
单例模式应用实例
- 构造器私有化=>防止直接new创建。
- 类的内部创建对象。
- 向外暴露一个静态的公共方法。getInstance();
饿汉式vs懒汉式
- 二者最主要的区别在于创建对象的时机不同:饿汉式是在类加载就创建了对象实例,而懒汉式是在使用时才创建。
- 饿汉式不存在线程安全问题,懒汉式存在线程安全问题。
- 饿汉式存在浪费资源的可能。因为如果程序员一个对象实例都没有使用,那么饿汉式创建的对象就浪费了,懒汉式是使用时才创建,就不存在这个问题。
- 应用场景:javaSE标准类中,java.lang.Runtime就是经典的单例模式。
final关键字
final可以修饰类、属性、方法和局部变量;
在某些情况下,程序员可能有以下需求,就会使用final:
- 当不希望类被继承时,可以用final修饰。
- 当不希望父类的某个方法被子类覆盖【重写】时,可以用final关键字修饰。
- 当不希望类的某个属性的值被修改,可以用final修饰。public final double TAX_RATE=0.08
- 当不希望某个局部变量被修改时,可以使用final修饰。final double TAX_RATE=0.08
注意事项和细节讨论
- final修饰的属性又叫常量,一般用xx_xx_xx命令。
- final修饰的属性在定义时,必须赋初始值,并且以后不能再修改,赋值可以在:定义时;在构造器中;在代码块中,三个位置。
- 如果final修饰的属性是静态的,则初始化的位置只能是定义时;在静态代码块中;不能在构造器中。
- final类不能继承,但是可以实例化对象。
- 如果类不是final类,但是含有final方法,则该方法虽然不能重写,但是可以被继承。
- 一般来说,如果一个类已经是final类了,就没有必要再将方法修饰成final方法。
- final不能修饰构造方法(即构造器)。
- final和static往往搭配使用,效率更高,底层编译器做了优化处理。搭配使用,不会进行类加载。
- 包装类,String都是final类。
抽象类
当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法(用abstract关键字修饰该方法),那么这个类就是抽象类(用abstract来修饰该类)。
抽象类的介绍
- 用abstract关键字修饰一个类,这个类叫做抽象类。
- 用abstract关键字修饰一个方法,这个方法叫做抽象方法。
- 抽象的价值更多作用在于设计,是设计者设计好后,让子类继承并实现抽象类。
- 抽象类,在框架和设计模式中使用较多。
- 抽象类可以有任意成员(抽象类本质还是类),比如非抽象方法、构造器、静态属性等等。
- 抽象方法不能有主体,即不能实现。
- 如果一个类继承了抽象方法,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract类。
- 抽象方法不能使用private final static修饰,因为这些关键字都是和重写相违背的。
抽象类的应用:模板设计模式
集合
集合框架体系
collection
list
arrayList
vector
linkedList
set
hashset
linkedHashSet
treeSet
map
hashMap
LinkedHashMap
hashTable
properties
treeMap
经典接口
单列接口
collection
遍历方式
iterator
游标
- hasNext()判断集合中下一位置是否有值。
- next()返回游标下一位置的值,并将游标下移。
注意点:如果使用迭代器,对集合进行遍历之后,此时游标在集合的最下方。想再次遍历集合,需要给游标重新赋值,重新获取集合迭代器即可。
增强for
简易版的迭代器,它的底层就是调用的迭代器。
注意点:可用于集合,也可用于数组。
List
遍历方式
iterator
增强for
普通for
排序
使用冒泡结合集合中设置元素的方法完成。
ArrayList
注意事项
可以放null值,可以放多个null值。
底层实现为数组,可从源码中获得。
基本与vector相同,线程不安全的集合,效率高,但是不建议在多线程中使用。
底层结构与源码分析
arrayList中维护了一个object类型的数组elementData。
transient object【】elementData; // transient表示瞬间,短暂的
表示该属性不会被序列化。
transient object【】elementData; // transient表示瞬间,短暂的
表示该属性不会被序列化。
当创建arrayList对象时
- 如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
- 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。
扩容使用的是Array.copyOf();这样可以保留原来的数据,在保留原来数据的基础上扩容。
注意:idea有可能会打断点无法进入。需要设置:如图。
vector
注意事项
vector底层也是一个对象数组,protected Object[] elementData;
vector是线程同步的,即线程安全的,vector类的操作方法带有synchronized修饰。
但注意并不是需要线程安全,就一定要使用vector,如果这个集合,仅在一个线程
运行,那么完全可以使用arrayList,这样效率更高。
但注意并不是需要线程安全,就一定要使用vector,如果这个集合,仅在一个线程
运行,那么完全可以使用arrayList,这样效率更高。
底层结构与源码分析
vector底层结构与arrayList相同,都是数组。而底层的源码实现逻辑相同,只有细微区别:synchronized,扩容相关。
LinkedList
底层结构
linkedList底层维护了一个双向链表
linkedList中维护了两个属性first和last分别指向首节点和尾节点。
每个节点(Node)对象,里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表。
基于底层的结构,linkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高(没有扩容处理)。
源码分析
注意:因为LinkedList是双向链表,进行集合操作时,其实操作的是pre和next。
与arrayList的应用场景对比
LinkedList改查的时候,是从头开始。
set
- 无序,没有索引,但是每次取出的时候,顺序是固定的,它的底层是有一定算法的。
- 不允许元素重复,允许存在null,但是只能存在一个。
遍历方式:
- 迭代器。
- 增强for。
hashSet
hashSet的底层其实是hashMap,它在源码里直接调用了hashMap(数组+链表+红黑树)。
为什么不直接使用数组,而是加上了链表。。 为了提高效率。
为什么不直接使用数组,而是加上了链表。。 为了提高效率。
添加元素的底层机制
hashSet底层是HashMap
添加一个元素时,先得到hash值(不是hashcode值,hashcode值经过一个算法得到的结果值)-》会转成索引值。
找到存储数据表table,看这个索引为止是否已经存放有元素
如果没有,直接加入。
如果有,调用equals(可自行重写定义)比较,如果相同,就放弃添加,如果不同,则添加到最后。
如果没有,直接加入。
如果有,调用equals(可自行重写定义)比较,如果相同,就放弃添加,如果不同,则添加到最后。
扩容与树化转成红黑树的机制
hashSet底层是hashMap,第一次添加时,table数组扩容到16,临界值(threshold)是 16×加载因子(loadFactor)是0.75=12
如果table数组使用到了临界值12,就会扩容到16*2=32,新的临界值就是32*0.75=24以此类推
在java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树),否则仍然采用数组扩容机制。
- 这里的链表元素计算个数时,是从节点1开始算,也就是说第一个集合中的第一个值是算到数组中的。此时元素个数到达8就会进行扩容,或者树化。如果按照集合中的元素算,是集合中的元素个数达到9,才开始数组扩容或树化。
- 如果一个集合中只有一个位置上有元素,最多可以放10个,16->32->64,两次扩容就达到的树化标准(Node->TreeNode)。
注意事项:临界值12,不是说table中的数据达到12,而是说node的总值达到12.比如索引1上有7个元素,索引2上有6个元素,其他都为null,那么此时也会进行扩容。
linkedHashSett
- linkedHashSet是HashSet的子类;
- linkedHashSet底层是一个linkedHashMap,底层维护了一个数组+双向链表。
- linkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序(使用entry(不是node)中的before和after将插入的相邻元素连接起来),这使得元素看起来是以插入顺序保存的。
底层机制:
- 在linkedHashSet中维护了一个hash表(数组table)和双向链表(linkedHashSet有head和tail相当于hashset的first和end)。
- 每个节点都有before和after属性,这样可以形成双向链表。(注意也可以说成pre和next)
- 在添加一个元素时,先求hash值,在求索引,确定该元素在hash表中的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加【原则和hashset一样】)tail.next=newELement;// 简单指定 newElement.pre=tail; tail=newElement;
通过以上,我们遍历linkedHashSet也能确保插入顺序和遍历顺序一致。
treeSet
基本介绍:有序的不重复的集合【底层个 使用了treeMap】
当我们想有序排列时,可在构造方法中传入一个比较器(匿名内部类)。在匿名内部类中制定排序规则,需要注意的是,如果两个元素,按照制定的排序规则,比较为相同时,会不再添加该元素。比如,当使用字符串的长度进行排序,那么元素:a,ab,ac。3个元素,ac会加不进去。
当我们想有序排列时,可在构造方法中传入一个比较器(匿名内部类)。在匿名内部类中制定排序规则,需要注意的是,如果两个元素,按照制定的排序规则,比较为相同时,会不再添加该元素。比如,当使用字符串的长度进行排序,那么元素:a,ab,ac。3个元素,ac会加不进去。
当我们使用无参构造方法创建treeSet时。
没有传入比较器时,如果集合中的对象实现类了Comparator接口,那么在调用比较器,进行排序时是没有问题的,如String对象。如果是定义的对象如Student。需要实现Comparator接口,否则,会报错。classCastExeption
没有传入比较器时,如果集合中的对象实现类了Comparator接口,那么在调用比较器,进行排序时是没有问题的,如String对象。如果是定义的对象如Student。需要实现Comparator接口,否则,会报错。classCastExeption
双列接口
map
- map与collection并列存在。用于保存具有映射关系的数据:key-value
- map中的key和value可以是任何引用类型的数据,会封装到hashMap$Node对象中
- map中的key不允许重复,原因和hashSet一样。
- map中的value可以重复。
- map中的key可以为null,value也可以为null,key的null只能有一个,value的key可以有多个。
- 常用String类做为map的key,但是任何引用类型的数据都可以作为key。
- key和value之间存在单向一对一关系,即通过指定key总能找到对应的value。
- map存放的数据,一对k-v是存放在node中的,node实现了map.entry<k,v>接口。为了方便遍历,增加了Set set=map.keyset;Collection values=map.getValues(); 其实都是指向了node中k,v,并不是底层实现,存在了set和values中。可以通过set和values中对象的地址与node中的对象地址对比,来查看获得。
遍历
keyset+map.get(key)
迭代器
增强for
values
迭代器
增强for
entrySet
迭代器
增强for
hashMap
概要:
- hashMap是map接口使用频率最高的实现类。
- hashMap是以k-v对的方式来存储数据(hashMap$node类型)
- key不能重复,但是值可以重复,允许使用null键和null值,如果添加相同的key,则会覆盖原来的k-v,等同于修改。(key不会被替换,value会被替换),阅读源码可得。
- 与hashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的。(jdk8的hashMap底层 数组+链表+红黑树)
- hashMap是线程不安全,没有实现同步互斥,方法上没有synchronized关键字。
hashMap底层机制-扩容【与hashset相同,其实hashset底层原理就是hashmap】
- hashMap底层维护了Node类型的数组table,默认为null。
- 当创建对象时,将加载因子(loadfactor)初始化为0.75。
- 当添加key-value,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素,如果没有元素直接添加。如果该索引处有元素,继续判断该元素的key和准备加入的key是否相等,如果相等,则直接替换value;如果不相等需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容。
- 第一次添加,则需要扩容table容量为16,临界值(threshold)为12(16*0.75)。
- 以后再扩容,则需要扩容table容量为原来的2倍(32),临界值为原来的2倍,即24,以此类推。
- 在java8中,如果一条链表的元素个数超过TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树)。
注意点:当table中达到临界值(table长度×0.75)会触发扩容。还有一种情况是,当table中在一个索引位置上,也就是一个链表上,达到8个之后且table的长度不够64,此时不会去树化,而是先去扩容,直到table的长度达到64。
hashTable
基本介绍:
- hashTable的键和值都不能为null(底层会判断,报空指针异常)。
- hashTable的使用方法基本上和hashMap一样。
- hashTable的线程安全的(synchronized),hashMap是线程不安全的。
- hashTable的初始化,集合长度为11,扩容机制为11*2+1,再次扩容为23,负载因子为0.75。
properties
基本介绍:
- properties类继承自hashTable类并且实现了map接口,也是使用一种键值对的形式来保存数据。
- 它的使用特点和hashTable类似。
- properties还可以用于从xxx.properties文件中,加载数据到properties类对象,并进行读取和修改。
treeMap
基本介绍:有序的不重复的集合
当我们想有序排列时,可在构造方法中传入一个比较器(匿名内部类)。在匿名内部类中制定排序规则,需要注意的是,如果两个元素,按照制定的排序规则,比较为相同时,会不再添加该元素。比如,当使用字符串的长度进行排序,那么元素:a,ab,ac。3个元素,ac会加不进去。
当我们想有序排列时,可在构造方法中传入一个比较器(匿名内部类)。在匿名内部类中制定排序规则,需要注意的是,如果两个元素,按照制定的排序规则,比较为相同时,会不再添加该元素。比如,当使用字符串的长度进行排序,那么元素:a,ab,ac。3个元素,ac会加不进去。
当我们使用无参构造方法创建treeSet时。
没有传入比较器时,如果集合中的对象实现类了Comparator接口,那么在调用比较器,进行排序时是没有问题的,如String对象。如果是定义的对象如Student。需要实现Comparator接口,否则,会报错。classCastExeption
没有传入比较器时,如果集合中的对象实现类了Comparator接口,那么在调用比较器,进行排序时是没有问题的,如String对象。如果是定义的对象如Student。需要实现Comparator接口,否则,会报错。classCastExeption
集合常用场景
主要取决于业务操作特点,然后根据集合实现类特性进行选择。
1)先判断存储的类型(一组对象【单列】或一组键值对【双列】)
2)一组对象:collection接口
允许重复:list
增删多:linkedList【底层维护了一个双向链表】
改查多:arrayList【底层维护object类型的可变数组】
不允许重复:set
无序:hashSet【底层个是hashMap,维护了一个哈希表即(数组+链表+红黑树)】
排序:treeSet
插入和取出顺序一致,linkedHashSet,维护数组+双向链表
3)一组键值对:map
键无序:hashMap【底层jdk7:数组+链表jdk8:数组+链表+红黑树】
键排序:treeMap
插入和取出顺序一致:LinkedHashMap,维护数组+双向链表
读取文件:properties
1)先判断存储的类型(一组对象【单列】或一组键值对【双列】)
2)一组对象:collection接口
允许重复:list
增删多:linkedList【底层维护了一个双向链表】
改查多:arrayList【底层维护object类型的可变数组】
不允许重复:set
无序:hashSet【底层个是hashMap,维护了一个哈希表即(数组+链表+红黑树)】
排序:treeSet
插入和取出顺序一致,linkedHashSet,维护数组+双向链表
3)一组键值对:map
键无序:hashMap【底层jdk7:数组+链表jdk8:数组+链表+红黑树】
键排序:treeMap
插入和取出顺序一致:LinkedHashMap,维护数组+双向链表
读取文件:properties
collections
排序操作:
- reverse(list):反转list中元素的顺序
- shuffle(list):对list集合元素进行随机排序
- sort(list):根据元素的自然顺序对指定list集合元素按升序排序
- sort(list,Comparator):根据指定的Comparator产生过的顺序对list集合元素进行排序
- swap(list,int i,int j):将指定list集合中的i处元素和j处元素进行交换
查询、替换操作:
- object max(collection):根据元素的自然顺序,返回给定集合中的最大元素
- object max(collection,Comparator):根据Comparator指定的顺序,返回给定集合中的最大元素
- object min(collection)
- object min(collection,Comparator)
- int frequency(collection,object)返回指定集合中指定元素的出现次数
- void copy(List dest,List src):将src中的内容复制到dest中
- boolean replaceAll(List list,Object oldvalue,Object newValue):使用新值替换List对象的所有旧值
Java概述
Java历史
95年发布第一个版本
java之父-詹姆斯·高斯林 (James Gosling)
现在公司使用更多的版本:java8、java11
所属公司:之前所属sun公司,后被甲骨文收购。
Java技术体系平台
JavaSE(Java Standard Edition)标准版
支持面向桌面级应用(如Windows下的应用程序)的java平台,提供了完整的Java核心API,此版本以前成为J2SE
支持面向桌面级应用(如Windows下的应用程序)的java平台,提供了完整的Java核心API,此版本以前成为J2SE
JavaEE(Java Enterprise Edition)企业版
是为开发企业环境下的应用程序提供的一套解决方案。该技术体系中包含的技术如:Servlet、Jsp等,主要针对于Web应用程序开发。版本以前称为J2EE
是为开发企业环境下的应用程序提供的一套解决方案。该技术体系中包含的技术如:Servlet、Jsp等,主要针对于Web应用程序开发。版本以前称为J2EE
JavaME(Java Micro Edition)小型版
支持Java程序运行在移动终端(手机、PDA)上的平台,对JavaAPI有所精简,并加入了针对移动终端的支持,此版本以前成为J2ME
曾火过一段时间,后期受安卓影响较大。
支持Java程序运行在移动终端(手机、PDA)上的平台,对JavaAPI有所精简,并加入了针对移动终端的支持,此版本以前成为J2ME
曾火过一段时间,后期受安卓影响较大。
Java的特性
Java是面向对象的(oop)
Java语言是健壮的。Java的强类型机制、异常处理、垃圾的自动收集等是Java程序健壮性的重要保证。
Java语言是跨平台性的。【即一个编译好的.class文件可以在多个系统下运行,这种特性称为跨平台】
Java语言是解释型的【了解】
解释型语言:JavaScript、php、java 编译型语言:c、c++
区别:解释型语言,编译后的代码,不能直接被机器执行,需要解释器来执行,编译型语言,编译后的代码,可以直接被机器执行。
解释型语言:JavaScript、php、java 编译型语言:c、c++
区别:解释型语言,编译后的代码,不能直接被机器执行,需要解释器来执行,编译型语言,编译后的代码,可以直接被机器执行。
Java常用工具
nodepad++、editplus、sublime、idea、eclipse
JDK
Java运行机制及运行过程
Java语言的特点:跨平台性
因为有了JVM,同一个Java程序在三个不同的操作系统(windows、linux、mac)中都可以执行(针对三种系统,有3个版本Jvm,Jvm负责对class文件进行解释执行),这样就实现了Java程序的跨平台性。
Java语言的特点:跨平台性
因为有了JVM,同一个Java程序在三个不同的操作系统(windows、linux、mac)中都可以执行(针对三种系统,有3个版本Jvm,Jvm负责对class文件进行解释执行),这样就实现了Java程序的跨平台性。
Java虚拟机基本介绍
Jvm是一个虚拟的计算机,具有指令集并使用不同的存储区域。负责执行指令,管理数据、内存、寄存器,包含在JDK中。
对于不同的平台,有不同的虚拟机。
Java虚拟机机制屏蔽了底层运行平台的差别,实现了"一次编译,到处运行"。
Jvm是一个虚拟的计算机,具有指令集并使用不同的存储区域。负责执行指令,管理数据、内存、寄存器,包含在JDK中。
对于不同的平台,有不同的虚拟机。
Java虚拟机机制屏蔽了底层运行平台的差别,实现了"一次编译,到处运行"。
JDK、JRE基本介绍
- JDK的全称(Java Development Kit Java开发工具包),JDK=JRE+Java的开发工具包【java、javac、Javadoc、javap等】。JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包含了JRE。
- JRE(Java Runtime Environment Java运行环境),JRE=JVM+Java的核心类库【类】。包括Java虚拟机(JVM Java Virtual Machine)和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机只需要安装JRE即可。
安装、配置
用户变量:电脑当前用户生效
系统变量:所有用户生效
系统变量:所有用户生效
快速入门
运行
- 有了可执行的java程序(Hello.class字节码文件)
- 通过运行工具java.exe对字节码文件进行执行,本质就是.class装载到jvm机执行。(注意:如果Hello.java源文件需要重新编译,生成新的class文件后,在进行执行,才能生效)。
注意细节:
- 一个源文件中最多只有一个public类,但是其他类的个数不限。
- 编译后,每一个类对应一个class文件。
- 源文件名必须与public的类名对应。
注释
可读性,为己为人
单行注释//
多行注释/**/
注释中的内容不会被Jvm执行
多行注释中不允许嵌套多行注释。
文本注释
注释内容可以被jdk提供的工具javadoc所解析,生成一套以网页文件形式体现的该程序的说明文档,一般写在类。
基本格式
/**
@author
*/
生成对应的文档注释:javadoc -d 文件夹名 -xx -yy Demo3.java
举例:javadoc -d D:\\temp -author Demo3.java 生成一个文档注释,位置在d盘下的temp文件中,生成的标签有author,其他标签不生成,对应的java类为Demo3。
基本格式
/**
@author
*/
生成对应的文档注释:javadoc -d 文件夹名 -xx -yy Demo3.java
举例:javadoc -d D:\\temp -author Demo3.java 生成一个文档注释,位置在d盘下的temp文件中,生成的标签有author,其他标签不生成,对应的java类为Demo3。
代码规范(基础版)
类、方法的注释要以javadoc的方式来写。
非javadoc的注释,一般是给代码的维护者看的,着重告诉读者为什么这样写,如何修改,注意什么问题,一般用单行、多行注释。
注释代码的格式:使用tab右移,使用shift+tab左移。
运算符和=两边习惯各加一个空格。
源文件使用utf-8编码,如果是dos窗口javac、java命令操作文件时,为了能阅读,它的编码是gbk。
代码行宽度不要超过80字符。idea中有个右竖线,按照那个就可以。
代码编写次行风格{在方法名同行(推荐)和行尾风格{另起一行。
dos命令
dos介绍:
disk operating system磁盘操作系统。
disk operating system磁盘操作系统。
常用dos命令
- 查看当前目录有什么: dir
- 切换到其他盘: cd
- 切换到当前盘:cd 绝对路径,cd 相对路径
- 切换到上一级:cd ..
- 切换到根目录:cd \
查看目录下的所有文件夹:tree 目录
清屏:cls
退出:exit
了解其他命令,主要操作都在linux系统中,而且命令会发生变化,此处了解即可。
- md【创建目录】rd【删除目录】copy【拷贝文件】copy+文件名+拷贝到的目录以及新文件名 del【删除文件】move【剪切】
- echo【输入内容到文件】echo ok->hello.txt 创建一个hello.txt内容为ok
- type【控内容到文件】type nul->hello.txt 创建一个hello.txt内容为空
相对路径-绝对路径
如图举例: ..\ 上一级目录
变量
变量介绍
为什么需要变量?
不论是使用那种高级程序语言编写程序,变量都是其程序的基本组成单位。
不论是使用那种高级程序语言编写程序,变量都是其程序的基本组成单位。
概念
变量相当于内存中一个数据存储空间的表示,可以把变量看做一个房间的门牌号,通过门牌号可以找到房间,而通过变量名可以访问到变量值。
变量的使用步骤
声明变量 int a; 赋值 a=4;或者int a=4;
变量相当于内存中一个数据存储空间的表示,可以把变量看做一个房间的门牌号,通过门牌号可以找到房间,而通过变量名可以访问到变量值。
变量的使用步骤
声明变量 int a; 赋值 a=4;或者int a=4;
注意事项:
- 变量表示内存中的一个存储区域【不同的变量,类型不同,占用的空间大小不同】比如int4个字节,double就是8个字节。
- 该区域有自己的名称【变量名】和类型【数据类型】
- 变量必须先声明,后使用,即有顺序
- 该区域的数据可以在同一类型范围内不断变化。(重新赋值)
- 变量在同一个作用域内不能重名。
- 变量=变量名+值+数据类型,变量三要素。
+号
当左右两边都是数值型时,则做加法运算
当左右两边有一方为字符串,则做拼接运算
运算顺序,从左到右
数据类型
类型体系
基本数据类型
数值型
整数类型,存放整数(byte【1】,short【2】,int【4】,long【8】)
浮点(小数)类型(float【4】,double【8】)
字符型(char【2】)
布尔型(boolean【1】),存放true,false
引用数据类型(面向对象再讲)
类(class)
接口(interface)
数组【】
类型详讲
整型
整型基本介绍
整数类型的使用细节:
Java各整数类型有固定的范围和字段长度,不受固定OS【操作系统】的影响,以保证Java程序的可移植性。
Java的整型常量默认为int型,声明long型常量须后加‘l’或‘L’
Java程序中变量常声明为int型,除非不足以表示大数,才使用long
bit:计算机中最小存储单位。byte:计算机中基本存储单元1byte=8bit【二进制中详讲】。
Java各整数类型有固定的范围和字段长度,不受固定OS【操作系统】的影响,以保证Java程序的可移植性。
Java的整型常量默认为int型,声明long型常量须后加‘l’或‘L’
Java程序中变量常声明为int型,除非不足以表示大数,才使用long
bit:计算机中最小存储单位。byte:计算机中基本存储单元1byte=8bit【二进制中详讲】。
浮点型
浮点型基本介绍
浮点型使用细节:
- 与整型类似,Java浮点类型也有固定的范围和字段长度,不受具体os影响。【float4个字节double8个字节】
- Java的浮点型常量(具体值)默认是double型,声明float型常量,须后加‘f’或‘F’
- 浮点型常量有两种表示形式:
- 十进制数形式:如:5.12 512.0f .512(如果是零点几,零可以省略)
- 科学计数法形式:如:5.12e2[5.12*10的2次方] 5.12E-2[5.12/10的2次方]
- 通常情况下,应该使用double型,因为它比float型更精确【小数保留的位数更多】。
- 浮点数使用陷阱:2.7与8.1/3比较。它俩直接用==为false. 那怎么判断处理,可以对它倆的差值取绝对值,在精度范围内判断,如果小于精度,为相。比如math.abs(a-b)<0.000001.
字符型
基本介绍
字符类型可以表示单个字符,字符类型是char,char是两个字节(可以存放汉字),多个字符用字符串string
字符类型可以表示单个字符,字符类型是char,char是两个字节(可以存放汉字),多个字符用字符串string
使用细节
- 字符常量是用单引号''括起来的单个字符
- 允许使用转义字符'\'来将其后的字符转变为特殊字符型常量,如char c='\n'; \n表示换行符。
- char本质是一个整数,在输出时,是unicode码对应的字符。http://tool.chinaz.com/Tools/Unicode.aspx
- 可直接给char赋一个整数,然后输出时,会按照对应的unicode字符输出。38889 对应韩
- char类型是可以进行运算的,相当于一个整数,因为它都对应有unicode码。'a'+1 直接输出为字符int('a'+1)输出为整数。
本质探讨
- 字符型 存储到计算机中,需要将字符对应的码值(整数)找出来,比如'a' 存储:'a'->码值97->二进制->存储;读取:二进制->97->'a'->显示
- 字符和码值的对应关系是通过字符编码表决定的(是规定好的)
字符编码表的介绍
ASCII(ASCII编码表 一个字节表示,一个128个字符)
unicode固定大小的编码,使用两个字节来表示字符,字母和汉字统一都占用两个字节,这样浪费空间。
utf-8大小可变的编码,字母使用1个字节,汉字使用3个字节
gbk可以表示汉字,而且范围广,字母使用1个字节,汉字2个字节
gb2312可以表示汉字,gb2312<gbk
big5码繁体中文,台湾,香港
ASCII(ASCII编码表 一个字节表示,一个128个字符)
unicode固定大小的编码,使用两个字节来表示字符,字母和汉字统一都占用两个字节,这样浪费空间。
utf-8大小可变的编码,字母使用1个字节,汉字使用3个字节
gbk可以表示汉字,而且范围广,字母使用1个字节,汉字2个字节
gb2312可以表示汉字,gb2312<gbk
big5码繁体中文,台湾,香港
ASCII码介绍:
- 上世纪60年代,美国指定了一套字符编码(使用一个字节),对英语字符与二进制位之间的关系做了统一规定。这被称为ASCII码码。ASCII码码一共规定了128个字符的编码,只占用了一个字节的后面7位,最前面的1位统一规定为0。【注意:此处表示,一个字节是可以表示256个字符的,ASCII码只用了128个字符】
- 缺点:不能表示所有字符。
unicode码介绍:
- unicode的好处:一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,使用unicode没有乱码的问题。
- unicode的坏处:一个英文字母和一个汉字都占用2个字节,这对于存储空间来说是浪费。
- 2的16次方是65536,所以最多编码是65536个字符。
- 编码0-127的字符是与ASCII的编码一样。比如'a'->0x61 'a'->ox0061,都对应的是97。因此unicode码兼容ASCII码。
utf-8编码介绍(了解)
- utf-8是互联网上使用最广的一种unicode的实现方式。
- utf-8是一种变长的编码方式。它可以使用1-6个字节表示一个符号,根据不同的符号而变化字节长度。
- 使用大小可变的编码,字母占用1个字节,汉字占用3个字节。
布尔型
基本介绍
- 也叫boolean类型,只允许取true\false,无null
- 占1个字节
- 适于与逻辑运算,一般用于程序流程控制。if while do-while for
类型转换
自动类型转换
基本介绍:
当java程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数据类型,这个就是自动类型转换。
char->int->long->float->double
byte->short->int->long->float->double
当java程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数据类型,这个就是自动类型转换。
char->int->long->float->double
byte->short->int->long->float->double
自动类型转换注意和细节:
有多种类型的数据混合运算是,系统首先自动将所有数据转换成容量最大的那种数据类型,在进行计算。
当我们把精度(容量)大的数据类型赋值给精度(容量)小的数据会报错,反之就会进行自动类型转换。
(byte,short)和char之间不会相互自动转化(规定)。注意byte a =10;short b=10;是可以的,计算机会查看给byte的赋值是否在它的取值范围内,如果在,可以。如果不在,会报错。范围-128~127。另外一种情况 int x=10; byte a=x;这种情况是不可以的,这种情况,x已经是int类型的数据了。
byte、short、char他们三者可以计算,在计算时会将数据类型提升为int。
boolean不参与转换。
自动提升原则:表达式结果的类型自动提升为操作数中最大的类型。
char a=‘男’;char b=‘女’;System.out.println(a+b); //此时输出的是两个码值的相加,是个数字,不是字符。
有多种类型的数据混合运算是,系统首先自动将所有数据转换成容量最大的那种数据类型,在进行计算。
当我们把精度(容量)大的数据类型赋值给精度(容量)小的数据会报错,反之就会进行自动类型转换。
(byte,short)和char之间不会相互自动转化(规定)。注意byte a =10;short b=10;是可以的,计算机会查看给byte的赋值是否在它的取值范围内,如果在,可以。如果不在,会报错。范围-128~127。另外一种情况 int x=10; byte a=x;这种情况是不可以的,这种情况,x已经是int类型的数据了。
byte、short、char他们三者可以计算,在计算时会将数据类型提升为int。
boolean不参与转换。
自动提升原则:表达式结果的类型自动提升为操作数中最大的类型。
char a=‘男’;char b=‘女’;System.out.println(a+b); //此时输出的是两个码值的相加,是个数字,不是字符。
强制类型转换
基本介绍:
自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符(),但可能造成精度降低或溢出,格外要注意。(int)1.9 是精度降低,得到了1;(byte)2000,是溢出,得到的是-48。
自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符(),但可能造成精度降低或溢出,格外要注意。(int)1.9 是精度降低,得到了1;(byte)2000,是溢出,得到的是-48。
细节说明:
只针对最近的操作数有效,往往会使用小括号提升优先级(int)(10*3.5)
char类型可以保存int的变量值,但不能保存int的变量,需要强转【这个正常呀,注意一下】。
只针对最近的操作数有效,往往会使用小括号提升优先级(int)(10*3.5)
char类型可以保存int的变量值,但不能保存int的变量,需要强转【这个正常呀,注意一下】。
基本数据类型和String类型的转换
基本介绍:
在程序开发中,我们会经常将两者互相转换。
在程序开发中,我们会经常将两者互相转换。
基本类型--》String:将基本类型的值+""。
String--》基本类型:通过基本类型的包装类调用parseXx方法即可。
Integer.parseInt("123");
Double.parseDouble("123.1");
依次有byte、short、long、float、boolean。
字符特殊一些 Char.charAt(0);将字符串第一个位置的元素转为字符。
Integer.parseInt("123");
Double.parseDouble("123.1");
依次有byte、short、long、float、boolean。
字符特殊一些 Char.charAt(0);将字符串第一个位置的元素转为字符。
注意事项:
将String转换为基本类型,注意String的值,“123”可以,“hello”自然就不行,会抛出异常。
将String转换为基本类型,注意String的值,“123”可以,“hello”自然就不行,会抛出异常。
运算符
运算符体系
算术运算符
赋值运算符
关系运算符【比较运算符】
逻辑运算符
位运算符【需要二进制基础】
三元运算符
运算符详讲
算术运算符
一览图
注意细节:
- %取模,看一个公式:a%b=a-a/b*b;举例:-10%3=-1; 10%-3=1; -10%-3=-1;
- i++,++i 自增效果一样。运算时:前者取自增前值,后者取自增后值。
关系运算符
一览图
注意:运算符"=="不要误写成"="
注意:运算符"=="不要误写成"="
逻辑运算符
一览图
&&短路与与&逻辑与的使用区别
- &&短路与:如果第一个条件为false,则第二个条件不会判断,最终结果为false,效率高(开发中使用&&)。
- &逻辑与:不管第一个条件是否为false,第二个条件都要判断,效率低。
||短路或与逻辑或|类比'与'即可。
逻辑异或:两个一样为false,两个不一样为true.
赋值运算符
赋值运算符的分类:
- 基本赋值运算符:=
- 复合赋值运算符:+= -= *= /= %=等。
赋值运算符特点:
从右往左:int num=a+b+c;
左边只能是变量,右边可以是变量、表达式、常量值。
复合赋值运算符a+=3;等价于a=a+3; 且具有强转效果(byte类型+=3;可以)
从右往左:int num=a+b+c;
左边只能是变量,右边可以是变量、表达式、常量值。
复合赋值运算符a+=3;等价于a=a+3; 且具有强转效果(byte类型+=3;可以)
三元运算符
基本语法:条件表达式?表达式1:表达式2;
运算规则:条件表达式为true,结果为表达式1,反之为表达式2。
运算规则:条件表达式为true,结果为表达式1,反之为表达式2。
运算符的优先级
一览表
运算符有不同的优先级,所谓优先级就是表达式运算中的运算顺序。
如上图,上一行的运算符总优于下一行。
使用时,用括号比较实用。
运算符有不同的优先级,所谓优先级就是表达式运算中的运算顺序。
如上图,上一行的运算符总优于下一行。
使用时,用括号比较实用。
- (),{}等。
- 单目运算符,++,--。
- 算术运算符
- 位移运算符
- 比较运算符
- 逻辑运算符
- 三元运算符
- 赋值运算符
标识符
标识符概念:
- Java对各种变量、方法和类等命名时使用的字符序列称为标识符。
- 凡是自己可以起名字的地方都叫标识符。
标识符的命名规则(必须)
- 26个英文字母大小写,0-9,_或者$组成。
- 数字不可以开头。
- 不可以使用关键字和保留字,但能包含关键字和保留字。
- 严格区分大小写,长度无限制。
- 标识符不能包含空格。
关键字一览表1)
关键字一览表2)
保留字一览表
命名规范(建议)
包名:多单词,都小写
类名、接口名:多单词首字母都大写,大驼峰。
变量名、方法名:小驼峰。
常量名:所有字母都大写,单词间下划线分隔。
包名:多单词,都小写
类名、接口名:多单词首字母都大写,大驼峰。
变量名、方法名:小驼峰。
常量名:所有字母都大写,单词间下划线分隔。
键盘输入语句
用来接收用户输入的数据。
- 导入该类所在包。
- 创建该类的对象。
- 调用里面的功能。
进制
进制介绍,对于整数有四种表示方式:
- 二进制:0、1,满二进一,以0b或0B开头。
- 十进制:0-9,满十进一。
- 八进制:0-7,满八进一。以数字0开头表示。
- 十六进制:0-9以及A(10)-F(15),满十六进一。以0x或0X开头表示。此处A-F不区分大小写。
进制转换
其他进制转十进制:
规则:从最低位(右边)开始,将每个位上的数提取出来,乘以该进制的(位数-1)次方,然后求和。
规则:从最低位(右边)开始,将每个位上的数提取出来,乘以该进制的(位数-1)次方,然后求和。
十进制转其他进制:
规则:将该数不断除以该进制,直到商为0为知,然后将每部得到的余数倒过来,就是对应的该进制数。如34转为二进制数是0b100010.
规则:将该数不断除以该进制,直到商为0为知,然后将每部得到的余数倒过来,就是对应的该进制数。如34转为二进制数是0b100010.
二进制转换成八进制
规则:从低位开始,将二进制每3位一组,转成对应的八进制数即可。
规则:从低位开始,将二进制每3位一组,转成对应的八进制数即可。
二进制转换成十六进制
规则:从低位开始,将二进制每4位一组,转成对应的十六进制数即可。
规则:从低位开始,将二进制每4位一组,转成对应的十六进制数即可。
八进制转换成二进制:
规则:将八进制数每1位,转换成对应的一个3位的二进制数即可。
规则:将八进制数每1位,转换成对应的一个3位的二进制数即可。
十六进制转换成二进制:
规则:将十六进制数每1位,转换成对应的一个4位的二进制数即可。
规则:将十六进制数每1位,转换成对应的一个4位的二进制数即可。
位运算(了解)
位运算的思考:>> <<等等。
二进制在运算的中的说明:
- 二进制是逢2进位的进位制,0、1是基本算符。
- 现代的电子计算机技术全部采用的是二进制,因为它只使用0、1两个数字字符,非常简单方便,易于用电子方式实现。计算机内部处理的信息,都是采用二进制数来表示的。二进制(binary)数用0和1两个数字及其组合来表示任何数。进位规则是“逢2进1”,数字1在不同的位上表示不同的值,按从右至左的次序,这个值以二倍递增。
原码、反码、补码运算规则
对于有符号的而言:
对于有符号的而言:
- 二进制的最高位是符号位:0表示正数,1表示负数。
- 正数的原码,反码,补码都一样。
- 负数的反码=它的原码符号位不变,其他位取反(0-》1,1-》0)
- 负数的补码=它的反码+1,负数的反码=它的补码-1
- 0的反码、补码都是0
- java没有无符号数,都是有符号的。
- 在计算机运算的时候,都是以补码的方式来运算的。
- 当我们看运算结果的时候,都看它的原码。
位运算符1)
案例1
案例2
案例3
位运算符2)
控制结构
顺序控制
分支控制
if、if-else、if-else if-else
单分支
双分支
多分支
嵌套分支(不超过3层,可读性不好)
switch
基本语法:
- switch关键字,表示switch分支。
- 表达式对应一个值。
- case 常量1:当表达式的值等于常量1,就执行语句块1。
- break:表示退出switch。
- 如果和case常量1匹配,就执行语句块1,如果不匹配,就继续匹配case常量2。此处需要注意case穿透,如果没有break,一直向下执行。
- 如果都没有匹配,则执行default。
注意事项和细节讨论
表达式数据类型,应和case后的常量类型一致,或者是可以自动转成可以相互比较的类型,比如输入的是字符,而常量是int。
switch(表达式)中表达式的返回值必须是:byte short int char enum String
case 子句中的值必须是常量,不能是变量,可以是表达式。
表达式数据类型,应和case后的常量类型一致,或者是可以自动转成可以相互比较的类型,比如输入的是字符,而常量是int。
switch(表达式)中表达式的返回值必须是:byte short int char enum String
case 子句中的值必须是常量,不能是变量,可以是表达式。
swith与if的比较
如果判断的具体数值不多,而且符合byte short 等6种类型。虽然两个都可以使用,建议使用switch语句。
其他情况,如区间判断,boolean类型判断,使用if,if的使用范围更广。
循环控制
for
基本语法:
for(循环变量初始化;循环条件;循环变量迭代){
循环操作(语句);
}
for(循环变量初始化;循环条件;循环变量迭代){
循环操作(语句);
}
编程思想:
- 化繁为简
- 先死后活
while
基本语法,while循环也有四要素只是位置不一样:
循环变量初始化;
while(循环条件){
循环体(语句);
循环变量迭代;
}
循环变量初始化;
while(循环条件){
循环体(语句);
循环变量迭代;
}
dowhile
基本语法:
循环变量初始化;
do{
循环体(语句);
循环变量迭代;
}while(循环条件);
先执行,再判断,也就是说,一定会执行一次。
循环变量初始化;
do{
循环体(语句);
循环变量迭代;
}while(循环条件);
先执行,再判断,也就是说,一定会执行一次。
多重循环
将一个循环放到另一个循环体内,也就是嵌套循环。一般两层,最多不超过3层,可读性差。
break
break语句出现在多层嵌套的语句块中,可以通过标签指明要终止的是哪一层的语句快。
- break 语句可以指定退出那一层,不指定时为最近的循环体。
- 循环语句。上的label1: 为标签名。
- 实际开发中,尽量不适用标签。
continue
continue语句使用细节与break一致,区别在于continue语句用于结束本次循环,继续执行下一次循环。
return
return使用字方法,表示跳出所在的方法(如果方法是main方法,会退出程序)。
数组、排序、查找
数组
数组的使用
使用方式1-动态初始化
数组的定义:数组类型【】数组名=new 数组类型【大小】;
数组的引用: 数组名【下标或者叫索引】
数组的定义:数组类型【】数组名=new 数组类型【大小】;
数组的引用: 数组名【下标或者叫索引】
使用方式2-动态初始化
先声明,再创建。
数据这类型 数组名【】;
数组名=new 数据类型【大小】;
注意 数组名和【】,两个顺序谁在前都可以。
先声明,再创建。
数据这类型 数组名【】;
数组名=new 数据类型【大小】;
注意 数组名和【】,两个顺序谁在前都可以。
数组方式3-静态初始化
数据类型 数组名 【】={元素值,元素..}
数据类型 数组名 【】={元素值,元素..}
数组使用注意事项和细节
- 数组中的元素可以是任何数据类型,但是不能混用,是多个相同的数据类型。
- 数组创建后,如果只定义大小,没有赋值,此时数组是有默认值的。int 0 ,short 0,byte 0, long 0, float 0.0, double 0.0, char \u0000, boolean false ,String null。
- 数组的下标是从0开始的。
- 数组的使用步骤:1声明数组并开辟空间2给数组各个元素赋值3使用数组
- 数组属于引用类型,数组型数据是对象(object)
数组的赋值机制
基本数据类型赋值,值传递【值拷贝】
数组类型赋值,引用传递(赋的值是地址)
基本数据类型赋值,值传递【值拷贝】
数组类型赋值,引用传递(赋的值是地址)
值传递与引用传递的区别
数组的翻转
数组的扩容、缩减
原理:数组的扩容等,都是复制原有数组,创建新的数组,效率是很低的。
注意点:创建新的数组之后,之前的数组,在堆中没有指引之后,会被Jvm回收。
排序
排序的分类
内部排序:
指将需要处理的所有数据都加载到内部存储器中进行排序。包括(交换式排序法、选择式排序法、插入式排序法)
指将需要处理的所有数据都加载到内部存储器中进行排序。包括(交换式排序法、选择式排序法、插入式排序法)
外部排序法:
数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法、直接合并排序法)
数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法、直接合并排序法)
经典排序
冒泡排序法
基本思想:
通过对待排序序列从后向前(从下标较大的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就像水底下的气泡一样向上冒。
通过对待排序序列从后向前(从下标较大的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就像水底下的气泡一样向上冒。
查找
顺序查找(挨个,从头到尾比较)
二分法查找(算法时讲解)
二维数组
- 定义形式:int [][]
- 理解:原来的一维数组的每个元素也是一维数组时,就构成了二维数组,在结构上相当于嵌套。
- 获取值:arr[i],arr[i][j]
二维数组的使用
使用方式1:动态初始化
语法:类型【】【】数组名=new 类型【大小】【大小】。
举例:int arr [][]=new int[2][3].
语法:类型【】【】数组名=new 类型【大小】【大小】。
举例:int arr [][]=new int[2][3].
使用方式2:动态初始化
先声明在开辟空间。
类型 数组名[][];
数组名= new 类型【大小】【大小】。
先声明在开辟空间。
类型 数组名[][];
数组名= new 类型【大小】【大小】。
使用方式3:列数不确定。
使用方式4:静态初始化
类型 数组名[][]={{值1,值2..},{值1,值2..},{值1,值2..}}
类型 数组名[][]={{值1,值2..},{值1,值2..},{值1,值2..}}
二维数组的内存图
二维数组使用细节和注意事项
声明方式:
int [] [] y
int [] y []
int y [] []
int [] [] y
int [] y []
int y [] []
二维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不同。
0 条评论
下一页