一.抽象类
1.概念:
如果一个类中,有抽象方法的话,那么这个类必须定义为抽象类 格式: abstract class 类名{} 注意: 抽象类中不一定有抽象方法呢,也可以是非抽象方法! 举例: 我们在开发中,应该将"概括性的事物"抽象化 不应该在事物中给出具体的体现 而是仅仅声明出来(就是没有方法体的方法) 让具体的事物进行重写
2.抽象方法:
和之前定义成员方法一样,只是没有方法体而已,没有{} 权限修饰符 abstract 返回值类型 方法名(参数列表);
3.抽象类的本质:
强制子类必须做的事情 重写抽象类的所有重写方法
4.抽象类的特点:
抽象类不能实例化 不能创建对象
5.抽象类的注意事项:
抽象类不能实例化,那么需用具体的子类实例化 如果抽象类的子类是抽象类,那么也不能实例化,但是一定存在最具体的子类,否则没有意义 抽象类的实例化---通过抽象类多态,父类引用指向子类对象,有最具体的子类 Fu fu = new Zi() ;Fu--->是一个抽象类类型
6.抽象类的成员特点:
1)成员变量 既可以是变量,也可以自定义常量:被final修饰
2)成员方法 可以是抽象方法,也可以是非抽象方法
3)构造方法:子类继承父类,存在继承关系,分层初始化 先让父类初始化,然后子类再进行初始化
4)注意事项: 子类的方法必须访问权限足够大,要么跟父类保持一致,否则报错
二.接口
1.概念
接口是一种规范,就是能够实现接口中的额外的功能 当前这个事物局部这个功能,就是体现事物能够实现的扩展的额外功能 接口---比抽象类还抽象的一种类型
2.格式
关键字:interface 接口名{ 接口名和类名的命名规范是一致的,"大驼峰命名法" }
3.接口的特点
接口中的方法:只能是抽象方法,不能有方法体; 接口特点:不能实例化(不能创建对象)
接口的实例化:是通过接口多态 接口的子实现类和接口的关系--->implements 实现关系 interface 接口名{} class 子实现类名 implements 接口1,接口2...{} 接口名 对象名 = new 子实现类名() ; 如果当前接口子实现类是一个抽象类,一定会存在抽象类的子类, 否则接口多态,子实现类new不了,所以当前抽象类一定有具体的子类
4.接口中的成员特点:
1)成员变量只能是常量,存在默认修饰符 public static final :可以省略不写
2)接口中的构造方法:没有构造方法,只是提供一些抽象方法,让子实现类实现这些方法
3)接口中的成员方法:只能是抽象方法(一般都是抽象方法) 存在默认修饰符:public abstract :可以省略不写
三.权限修饰符
private: 最小的 default: 默认修饰符 protected: 受保护的 public: 使用最最多的,访问权限足够大
权限修饰 在同一个包下的当前类中 同一个包下的子类中/无关类中 在不同包下子类中 private √ 默认修饰符 √ √ protected:受保护的 √ √ √ public :最大的 √ √ √
其他的修饰符: static:结合自定义去使用 定义自定义常量结合final public static final 数据类型 变量名 = 初始化数据; static还可以在工具类中---->工具类中的构造方法私有化,里面的方法都加入static,类名访问
abstract--->修饰类-->抽象类 还可以在成员方法中定义:抽象类中 =--->public abstract 返回值类型 方法名(参数列表) ; abstract在接口中定义的抽象方法---abstract可以省略 final结合static一块使用的: public static final 数据类型 变量名 = 初始化数据; 4.抽象面试题 1.如果一个类中没有抽象方法,那么把这个类定义为抽象类的意义何在? 属于"设计层面"----->设计某个类以及子类的结构 就是不想让直接 它new对象;肯定最终是有具体的子类存在
举例:
jdk提供提供的日历类---->Calendar 抽象类,不能new 提供了静态方法,返回值就是它自己本身 public static Calendar getInstance(){ 调用其他成员方法---->里面的本质就是 new 具体的子类对象(); }
2: abstract不能和哪些关键字使用?
abstract的应用场景:修饰类或者成员方法 修饰成员方法注意
: 1)abstract不能和private关键字使用,因为被private修饰的只能在当前类访问 而加入abstract需要让子类实现这个方法;已经超出了当前访问的范围,所以冲突
2)abstract不能和final一块使用,因为被final修饰的成员方法不能被重写的 而abstract修饰的抽象方法需要让子类强制重写的,所以冲突
3)abstract不能和static一块使用,因为被static修饰的方法,跟类相关的,随着类的加载而加载 而抽象方法需要被子类重写的,最终需要使用对象来抽象类多态:Fu fu = new Zi() ; 和static一块使用抽象方法在父类中又没有方法体,加载进行内存,没意义
3:接口和抽象类有什么区别?
1)成员的区别 接口的成员: 成员变量:只能常量,存在默认的修饰符public static final,可以省略不写 实际开发中,自定义一个常量,就定义一个接口,里面写常量即可
成员方法:一般说的抽象方法,可以是default默认方法或者静态方法, 必须有方法体 抽象方法,存在默认修饰符:public abstract 可以省略不写 构造方法: 没有 抽象类的成员: 成员变量:可以是常量(被final修饰),也可以是变量 成员方法:既可以是抽象方法,也可以是非抽象方法, 抽象方法中的abstract不能省略! 构造方法 :存在有参构造/无参构造都可以 因为还是继承关系,肯定分层初始化的 2)关系的区别 类与类的关系:extends 类:可能抽象类/具体类 继承关系只支持单继承,不支持多继承,可以多层继承 类与接口的关系:implements 实现关系 一个类继承另一个 类的同时可以实现多个接口 接口与接口的关系:extends :继承关系 可以单继承,可以多继承,也可以多层继承 3)设计理念的区别 抽象类: 最终肯定具体的子类,是继承关系 继承关系---体现的是一种"is a"的关系 抽象类多态 Animal(抽象类) a = new Dog() ;//狗是动物 a = new Cat() ;//猫是动物 接口: 子实现类实现接口---> 实现关系 描述的是事物本身不具备的功能,是通过后台学习培养出来的工 将这些功能----"额外的扩展功能" 核心思想---体现的是"like a "关系
4.形式参数如果是一个具体类,实际参数如何传递
实际参数需要当前类的具体对象 或者匿名对象也可以
5.如果方法的形式参数是引用类型
1)具体类:实际参数传递应该创建当前具体类对象
2)抽象类,实际参数需要传递应该创建当前抽象类的子类对象(抽象类多态)
3)接口:
4)数组:实际参数需要传递数组对象
5.带包的编译运行
1.手动方式
1)创建com文件夹 下面子文件qf 2)使用javac 先对HelloWorld的源文件先进行编译--->产生类名.class文件 (字节码文件) 3)将2)字节码文件放在qf子文件夹下 4)带包名来运行 java 包名.字节码文件的前缀类名
2.自动方式:
1)javac -d . java文件---->它会自动的产生包名的结果com下面有个qf子文件夹以及编译后的字节码文件在里面 2)只需要带包来运行即可 java 包名.字节码文件的前缀类名
六.内部类
1.概念:
一个类A中定义一个类B,将类B就称为类A的内部类 类A就是类B的外部类
2.特点:
1)成员内部类---在外部类的成员位置定义的类 2)局部内部类---在外部类的成员方法中定义的类
3.注意:
成员内部类中的成员访问外部类的成员变量包括私有 可以使用private修饰,保证数据的安全性
4.如何直接访问成员内部类的成员方法
将外部类的成员内部类---当做是外部类的成员 直接访问的方式: 前提条件:当前的成员内部类是非静态的 外部类名.内部类名 对象名 = new 外部类对象.内部类对象
5.局部内部类特点:
局部内部类也依然访问外部类的成员变量,包括私有
6.面试题:
1)局部内部类访问局部变量的时候,能访问码?局部变量有什么要求? jdk7或者jdk7以前,局部变量必须显示加入final修饰,否则访问报错 而jdk8已经jvm优化了,此时这个num2就是常量
2)使用反编译工具查看内部类的结构--->发现其实已经加入了final,为什么? 局部变量的生命周期是随着的方法的调用而存在,随着方法的调用结束而消失 而当前这个方法结束之后,num2局部变量也应该就不存在了 但是我们还在使用内部类对象访问它里面这个成员方法 而对象不会立即被GC立即回收,等待空闲的时候回收没有更多引用的对象 所以此时这些变量应该都是常驻内存,使用final定义----->常量 7.object类 1.Object类: 每个类都有Object作为超类--->父类的意思 所有的类都默认继承自Object
2.常用方法:
1)public final Class getClass() (重要):获取当前正在运行的Class类对象(字节码文件对象)
2)public int hashCode():常用类都已经重写了 理解: "一个地址值",不是实际意义的地址值,它是经过底层的哈希算法(hash)算出来的
3)public String toString() 返回对象的字符串表示形式, 结果应该是一个简明扼要的表达,容易让人阅读。建议所有子类覆盖此方法。' 不需要我们自定义---使用的idea提供的toString 自动生成: alt+ins---->toString()
4)public boolean equals(Object obj):比较对象是否相等 引用该类型比较的是地址值是否相同 5)protected Object clone()throws CloneNotSupportedException 创建并返回此对象的副本 本质就是复制对象---"浅克隆" Object里面的clone方法 protected native Object clone() throws CloneNotSupportedException; 本地方法---->非Java语言实现的,通过系统资源调用的 如果此对象的类不实现接口Cloneable ,没有成员方法就是标记接口 如果某个对象的类实现这个接口的话,那么就说明这个类可以使用Object的clone来进行对象的复制 则抛出CloneNotSupportedException
3.==和equals的区别
1)==:如果连接都是两个基本数据类型:比如int 比较的是数据值是否相等
2)如果连接的是引用类型,那么比较的是地址值是否相同 equals()是Object类的方法 源码 public boolean equals(Object obj) { return (this == obj); } 如果我们不重写Object的equals方法, 默认比较的是两个引用类型的地址值是否相同, 如果重写了equals方法而且同时重写了hashCode()比较的是成员信息是否相同
3)几乎所有类都会覆盖 论何时覆盖该方法equals(),通常需要覆盖hashCode方法 4)工具生成: alt+ins--->eauals and hashCode
七.返回值
返回值问题
方法的返回值要么是基本数据类型,要么就是引用数据类型 方法的返回值是基本类型:是什么类型的时候,使用对应的类型接收即可
返回值是引用类型:
如果是具体类,需要返回的当前类的具体对象 如果是抽象类,需要返回的是当前抽象类的子类对象 如果是接口,需要返回的是接口的子实现类对象
八.匿名内部类
1.见名知意:没有名字的类
2.一般情况很少使用具体类的匿名内部类,因为具体类本身就可以new对象
3.应用场景: 就是抽象类和接口中使用最多,其中接口使用最多的
4.固定格式 一个类中的某个局部位置使用 new 类名(一般情况下:都是抽象类)或者接口名(){ 重写抽象类或者接口的抽象方法(){ }};
5.本质:就是继承了该抽象类或者实现了该接口的子类对象
6.注意事项
1)形参问题: 方法的形式参数如果是一个抽象类,调用方法的时候实际参数应该传递的当前抽象类的子类对象 方法的形式参数如果是一个接口类型,调用方法的时候,需要传递接口的子实现类对象
2)返回值问题 方法的返回值如果是一个接口,需要接口的子实现类对象
十.键盘录入细节
1)先录入的String,在录入i1nt,没问题
2)先录入int,在录入String,有问题 因为"回车符号"---->就是换行---->当空字符进去了,所以第二个数还没有录入的就完了
解决方案:
1)String nextLine() 录入一行数据,--->官方用法 使用另一种方法:public String next() 录入的指定的字符串内容(通用格式)
2)就要使用nextLine()方法录入STring,在录入String之前,重新创建一个新的键盘录入对象,也可以! String类型使用时最多的-->所以以后如果有int类型的录入----> 可以都是用String数据接收(nextLine())---> 然后将String-->Integer->int(前提---->录入的"数字字符串")
十一. String类(重点)
1.String类: Java程序中的所有字符串文字(例如"abc" )都被实现为此类的实例 特点: 字符串是不变的,它们的值在创建后不能被更改; String str = "abc"; //创建字符串对象的标准格式(建议) 直接是在常量中查看是否存在这个字符串常量,如果存在,就会查找常量池的地址值,否则,常量池中开辟空间
2.String的构造方法 1)String() :空参构造 2)String(byte[] bytes) :有参构造,里面是字节数组(将byte[]--String) 解码过程(将看不懂的内容--->字符--->平台默认字符集现在"utf-8",所以不用带字符集!) 3)String(byte[] bytes, int offset, int length) :将一部分字节数组--->字符串 参数1:字节数组 参数2:指定的位置开始 参数3:指定的长度 4)String(char[] value) :将字符数组---->字符串 5)String(char[] value, int offset, int count) :将一部分字符数组--->字符串 参数1:字符数组对象 参数2:从指定位置开始 参数3:记录数多少个 6)String(String original) :构造的字符串对象,参数为字符串常量值 3.""空字符序列和null的区别 "":说明有内容,空的,依然可以使用String类型里面的所有功能 null:空对象,不能在使用String的方法,在使用,就空指针异常NullPointerException 4.String常用的判断功能 public boolean startsWith(String xxx) :以指定的字符串开头 public boolean endsWith(String xxx):指定的字符串结尾 public boolean equals(Object obj):判断字符串的内容是否相同 public boolean equalsIgoreCase(String str):不区分大小写比较内容是否相同 public boolean isEmpty():判断字符串是否空字符序列 public boolean contains(String str):是否包含指定的字符串 5.String常用的获取功能 char charAt(int index):返回指定索引出的字符 String[] spilt(String regex) :使用指定的分割符号拆分字符串,返回的字符串数组 String concat(String str):拼接功能,和指定字符串拼接为新的字符串内容 String subString(int beginIndex):从指定的位置开始截取,默认截取到末尾; String subString(int beginIndex,int endIndex):从指定位置开始截取到指定位置结束 (不包含endIndex位置,包含在endIndex-1位置) 6.String类的转换功能: public char[] toCharArray():将字符串转换为字符数组 public byte[] getBytes():将字符串转换成字节数组---使用平台默认字符集编码 String的构造方法---String(byte[] bytes):使用平台默认字符集解码 public String toLowerCase():将字符串转换成小写 public String toUpperCase():将字符串转换成大写 万能方法:将任何数据类型转换成String public static String valueOf(int/double/float/char[]/Object i)\ 7.String类的其他功能 public String replace(char oldChar,char newChar):将指定的字符使用新字符进行替换 public String replace(String oldStr,String newStr):替换指定字符串 public String trim():去除两端空格 public int compareTo(String anotherString):按照字典顺序比较 12.String面试题 1.数组中有没有length(),String类中有没有length(),集合中有没有length()方法? 数组中没有length(),叫length属性 String类有的length():获取字符串长度 获取功能之一:int length() 集合中没有,是sise():获取集合的元素数 2. String s = "hello"; String s = new String("hello") ; 有什么区别?分别创建了几个对象呢?
实际开发中:将常量赋值给字符串和new String("常量")有区别,实际开发中使用的是前者 1)将常量赋值给字符串:常量赋值的 形式,直接在常量中找,是否存在常量 如果存在,就直接返回常量池地址 如果不存在,那么现在常量池中开辟空间,然后再去把常量池地址赋值给变量s,从而有地址指向 2)new String("常量"): new 对象,---需要在堆内存空开辟空间(堆内存空间地址值)而里面有一个字符串常量"hello" 然后在常量池中找,如果有,直接返回常量池地址值,如果没有,开辟常量池的空间地址 不推荐,因为它的内存消耗很大
4.String和StringBuffer的区别? String是一个特殊的引用类型,形参的改变不会实际参数,效果和基本类型一致 String是常量,一旦被赋值,其值不能被更改
StringBuffer:是线程安全的一个类,支持可变的字符序列, 引用类型除过String之外,形参改变直接影响实际参数
3.StringBuffer和StringBuilder有什么区别? 共同点:就是具有相互兼容的API(StringBuffer能用的StringBuilder也可以) 都是支持可变的字符序列,不断在字符串缓冲区进行追加字符 不同点: StringBuffer是线程安全的类,同步操作,执行效率低 StringBuilder是线程不安全的类,不同步的操作,执行效率高
单线程环境下都使用StringBuilder去替换StringBuffer,因为执行效率高 单线程环境:只考虑执行效率,不考虑安全 多线程环境:首先要考虑安全,然后在说效率
十二. StringBuffer
1.概念
字符串缓冲区--->里面都存储的可变的字符序列,但是它的类型StringBuffer类型
2.构造方法
StringBuffer() 空参构造 StringBuffer(String str):有参构造 "hello" --->容量大小--->16+5=21 中文很特殊--->超过某个容量值,系统会重写分配 StringBuffer(int capacity):指定容量大小
3.获取功能:
int length():获取字符串缓冲区的长度(里面实际的字符序列的长度) public int capacity():获取缓冲区的容量大小 字符串缓冲区默认16个初始容器里(英文字符) 如果里面有字符序列,构造方法就是前两个使用居多 第一个是最常用的,空参构造方法--->创建字符串缓冲区对象 3.添加功能 public StringBuffer append(任何类型数据) :追加功能 (常用的) 返回值是字符串缓冲区本身,在缓冲区中的默认的字符序列后面依次追加
public StringBuffer insert(int offset,char c/String str): 返回值是字符串缓冲区本身,在指定的位置插入指定的字符或者字符串 4.反转功能: StringBuffer reverse() 返回字符串缓冲区本身 截取功能和String类型的截取功能一样 String subString(int beginIndex):从指定位置默认截取到末尾--->String String subString(int beginIndex,int endIndex): 从指定开始截取到指定位置结束endIndex-1出,返回的新的字符串
十四.Integer
1.引入
jdk5以后的新特性:自动拆装箱功能,每一个基本类型都自动装箱为对应的包装类类型 byte --- Byte short--- Short int --- Integer long --- Long float--- Float double --- Double char --- Character boolean --- Boolean
2.Integer类的有些成员变量
public static final int MAX_VALUE ;自定义常量 public static final int MIN_VALUE
3.静态方法
public static String toBinaryString(int i):将十进制数据--->二进制数据的字符串形式 public static String toOctalString(int i):将十进制数据--->八进制字符串形式 public static String toHexString(int i):将十进制数据---->十六进制数据的字符串形式
4.Integer类的作用
Integer的构造方法 Integer作为中间桥梁,,可以实现int类型和String类型的相互转换 同理,其他的基本类型和String类型的相互转换--使用基本类型对应的包装类类型 (实际开发中,int和long,double使用最多) Integer的内部缓存区特点IntegerCache
5.Integer的构造方法
Integer(int value)--->可以将基本类型数据--->Integer Integer(String s)throws NumberFormatException :将String--->Integer 形式参数必须为"数字字符串",否则如果不是数字字符串---> NumberFormatException出现数字格式化异常
6.自动拆装箱: 基本类型会提示为对应的包装类型--->称为"装箱" 而包装类类型会自动降为基本类型--->称为"拆箱"
7.Character:char类型保证类型
构造方法: Character(char value) 包含 char类型的值
8.Integer内部缓存区的IntegerCache的作用 将某个int的值直接赋值给Integer类型---> 调用底层的方法public static Integer valueOf(int i) 里面涉及到静态的私有的成员内部类:IntegerCache 如果当前我们的i的值是缓冲区的范围内:low:-128 high=127,是直接在缓冲区中取数据 否则,如果超出这个内部缓存区的范围的话,就执行else下面的代码 i3和i4:分别创建自己的对象,开辟堆内存空间!所以,地址值不同
十五.Date
1.概念
java.util.Date:表示日期对象,精确到毫秒
2.格式
创建日期的时候Date--->使用的空参构造方法 Date() public Date(long date) 是字符串日期的文本格式 String "2008-5-12" <--->java.util.Date 相互转换
3.转换的类:
DateFormat:日期格式化类:他是抽象类,不能new对象 public final String format(Date date):格式化 Date-->String public Date parse(String source) throws ParseException:解析 使用它的子类 SimpleDateFormat 构造方法:public SimpleDateFormat(String pattern): 参数是指定的一种模式 年 yyyy 月 MM 日期 dd 小时 hh 分钟 mm 秒数 ss
16.System
1.System类包含几个有用的类字段和方法,它不能被实例化 字段:(成员变量) public static final InputStream int ; 标准输入流 public static final PrintStream out ; 标准输出流 public static final PrintStream err ;标准的错误输出流 public static void gc()手动运行垃圾回收器 开启垃圾回收器 jvm需要调用实际本质方法是Object类的方法protected void finalize() throws Throwable public static long currentTimeMillis() 返回当前时间(以毫秒为单位) 这个方法:通过一个段规模比较的程序 public static void arraycopy(Object src, 原对象(数组) int srcPos, 原对象中的某个索引值 Object dest, 目标对象(数组) int destPos, 目标对象的指定的索引值 int length) 复制多少个长度,从指定原数组中复制元素到目标数组中
17.集合
1.集合和数组的区别
1)长度区别
数组的长度是固定的 集合的长度是可变的
2)存储数据类型的区别
数组存储的数据类型既可以是基本数据类型,也可以是引用数据类型 集合存储的数据类型只能是引用数据类型
3)存储元素的区别
数组存储的元素必须为同一种类型的元素 集合存储的元素(没有泛型),可以存储任意引用类型的元素
2.Collection集合
1)常用方法:
Object[] toArray():集合转换成对象数组 boolean remove(Object o):删除集合中指定的元素 void clear():删除所有元素(暴力删除) boolean contains(Object o):是否包含指定的元素
2)集合的高级功能:(了解) 带All的功能 boolean addAll(Collection c)添加一个集合中的所有元素 boolean containsAll(Collection c):包括一个集合中元素 包含一个集合中所有元素 boolean removeAll(Collection c):删除集合中的包含的元素 删除的元素一个只要包含,都存在,那么就删除了 boolean retainAll(Collection c):获取两个集合中交集元素, 返回值boolean表达的意思什么? A集合对B集合求交集,1)如果没有交集元素,那么A集合内容就是[](-->存储交集的元素 没有交集) 如果有交集,交集的元素是存在A集合中,返回值是看A集合中的元素内容是否发生变化 如果有变化--->true 如果没有变化--->false 3)泛型 1)概念: 就是集合对象的在创建的时候,就已经明确了存储的类型的限定!(模拟我们的数组的创建的格式一样) 2)泛型的好处: 提高了程序安全性,不会出现类型转换问题! 避免了强转类型转换的格式 将运行时期异常提前到了编时译期(编译通过不了,不能运行!)--- (使用迭代器的方式进行遍历) 4)Collection<E>集合遍历的方式 Object[] toArray() : 将集合转换成对象数组 Iterator iterator():Collection集合的迭代器 for(数据类型 变量名: 集合对象){ 使用变量名即可 } 5)迭代器 Collection 的成员方法 Iterator<E> iterator() :迭代器(理解原理) 使用Collection集合的迭代器遍历里面的字符串元素 while(it.hasNext()){//是否有可以遍历的元素,如果成立,不断获取 //Integer i = it.next() ; String s = it.next(); System.out.println(s+"----"+s.length()); } 迭代器Iterator(接口)的原理 就是实现迭代器中的方法,boolean hasNext(){} 判断是否有更多的元素可以遍历 E next():获取下一个可以遍历的元素 通过ArrayList集合的内部类Itr实现 类似于游标指针,当通过判断有由下一个可以遍历的元素,游标指针通过next()向下一个位置元素移动 直到当cursor如果达到了最大的集合的元素数,那么就不会再继续移动了,后面没有元素 否则,就出现NoSuchElementException:没有元素的异常
3.List 1)概念:
List集合是Collection的子接口
2)特点:
List集合可以允许元素重复,并且存储和取出一致
3)遍历方式 Object[] toArray() :
将集合转换成对象数组 Iterator iterator():Collection集合的迭代器 特有功能:E get(int index):通过索引获取元素内容+int size()方法普通循环实现 特有功能:列表迭代器 ListIterator listiterator(): ①增强for循环变量List集合 for(String s:list){ System.out.println(s); } ②普通for循环便利List集合 for(int x = 0 ; x <list.size() ; x ++){ String s = list.get(x); System.out.println(s); }
4)List的专有遍历方式:
第四种遍历方式 (前面三种:Collection的Iterator迭代器/传统方式Object[] toArray()/get(int index)+size()相结合) 列表迭代器 ListIterator<E> listIterator() ListIterator接口 正向遍历 boolean hasNext():判断是有更多下一个元素可以迭代(遍历) E next()获取下一个可以遍历元素 反向遍历(不能单独用,必须先有正向遍历) boolean hasPrevious():判断是否有更多的上一个元素可以迭代(遍历) E previous():获取上一个上一个可以遍历的元素
5)ConcurrentModificationException: 并发修改异常 使用迭代器去遍历元素,不能使用集合对象去操作元素,否则就出现并发修改异常 解决方案: 1)使用迭代器去遍历,迭代器添加元素--->List的特有遍历方式ListIterator有添加 2)使用集合遍历,集合添加元素
4.选择排序 思想: 使用0角标对应的元素依次和后面角标对应的元素进行比较,小的值往前放,第一次比较完毕 最小值就出现在最小索引处,依次这样比较,就可以得到一个排好序的数组
比较的次数:数组长度-1次 代码: public static void selectSort(int[] arr){ //外层循环比较的次数 for(int x = 0 ;x < arr.length-1; x++){ for(int y = x + 1 ;y< arr.length ;y++){ //依次和后面角标对应的元素进行比较,小的值往前放 if(arr[y] < arr[x]){ int temp = arr[x] ; arr[x] = arr[y] ; arr[y] = temp ; } } } }