(了解)Java的三大平台:Java SE ,java ME ,java EE
Java SE:Java标准平台,它允许开发软件运行在电脑桌面上,最经典的JavaSE 程序就是Java的开发工具Eclipse,同时JavaSE也是JavaEE的基础。
JavaME:Java微平台,用来开发移动上的设备和软件,比如早期功能机上的java游戏,当然现在开发手机软件使用iOS和Android 平台
和技术。
JavaEE:Java企业平台,针对web方向,主要应用于开发企业项目和互联网项目,如淘宝,京东,12306,各大银行网站等。
(掌握)Java的跨平台性
1.编写源文件(java文件),原文件中包含源代码(java源代码)
2.使用javac工具对源文件做编译操作,语法 javac 源文件.java
3.生成字节码后,使用java工具启动JVM,运行程序,语法:java拥有主方法的类名
4.控制台输出,显示结果
Java能跨平台的原因:
1.java文件经过编译后生成与平台无关的class文件
2.Java虚拟机是不跨平台的(不同平台需要安装不同平台的JVM)
(掌握)关键字和保留字
:goto,const是保留字
关键字和保留字都是小写
(重点)数据类型
八大基本数据类型:
1.基本数据类型:
整数类型:byte,short,int,long
小数类型:float,double
字符类型:char
布尔类型:boolean
2.引用数据类型:
数组,类,接口
注意:整数类型默认是int类型;小数类型默认是double类型;String是引用类型
表示long类型常量,要加L或者l,建议加L
表示float类型常量,要加F或f,建议加F
(掌握)基本数据类型
自动类型转换:范围小的数据类型会自动转换为范围更大的数据类型
如:int a=100;
long b=a;
正确
强制类型转换:范围大的数据类型不能自动转换为范围更小的数据类型,所以需要进行强制转换
如:long a=1L;
int b=a;
错误,正确写法为 int b=(int)a;
转换规则:byte、short、char---->int---->long—>float---->double
(了解)对于字符串而言,+符号表示连接操作,任何类型的数据和字符串相连接,结果都是字符串。
如:public static void main(String[] args) {
System.out.println(“123”+123+new Student(“sd”,12));
}
结果:123123java基础复习.面向对象.Student@15db9742
**
(掌握)自增自减运算符操作(只讨论自增)
**
++Result 表示对result+1之后的结果进行运算;
Result++ 表示对result变量加1之前的值加1;
如:
public static void main(String[] args) {
int result=1;
int a=result++;
int b=++result;
System.out.println(“a=”+a+";"+“b=”+b);
}
结果:a=1;b=3
(掌握)三元运算符
//如果99%20则返回偶数给result反之返回奇数给result
String result=99%20?”偶数”:”奇数”;
(掌握)逻辑运算符
&(与),|(或),&&(短路与),||(短路或) 区别
与 判断中有false则返回false
或 判断中有true则返回true
短路与 判断中如果左边为false,则右边进行判断,否则不参与判断,直接返回true
(|;||)有true返回true
短路或 判断中如果左边为true,则右边参与判断,否则不参与判断,直接返回false
(&;&&)有false返回false
(可记为:人多能偷懒,判断可以判一半)
(重点)控制循环
1.break表示结束当前所在循环
2.continue 表示跳过当前这一次循环,执行循环之后的操作语句,进入下一次循环操作
如:使4不被输出
public static void main(String args[]){
for(int i=0;i<10;i++){
If(i==4){
continue;
}
}
}
returen 表示结束当前循环所在方法,方法都结束了,循环也就结束了
(掌握)JVM 内存模型:
JVM内存模型: 程序计数器,虚拟机栈,native栈是线程私有的,堆是线程共有的,现在详细介绍JVM各个区块。
堆(Heap) 是java虚拟机所管理的内存中最大的一块内存区域,也是被各个线程共享的内存区域,该内存区域存放了对象实例及数组(但不是所有的对象实例都在堆中)。其大小通过-Xms(最小值)和-Xmx(最大值)参数设置(最大最小值都要小于1G),前者为启动时申请的最小内存,默认为操作系统物理内存的1/64,后者为JVM可申请的最大内存,默认为物理内存的1/4,默认当空余堆内存小于40%时,JVM会增大堆内存到-Xmx指定的大小,可通过-XX:MinHeapFreeRation=来指定这个比列;当空余堆内存大于70%时,JVM会减小堆内存的大小到-Xms指定的大小,可通过XX:MaxHeapFreeRation=来指定这个比列,当然为了避免在运行时频繁调整Heap的大小,通常-Xms与-Xmx的值设成一样。堆内存
= 新生代+老生代+持久代。在我们垃圾回收的时候,我们往往将堆内存分成新生代和老生代(大小比例1:2),新生代中由Eden和Survivor0,Survivor1组成,三者的比例是8:1:1,新生代的回收机制采用复制算法,在Minor
GC的时候,我们都留一个存活区用来存放存活的对象,真正进行的区域是Eden+其中一个存活区,当我们的对象时长超过一定年龄时(默认15,可以通过参数设置),将会把对象放入老生代,当然大的对象会直接进入老生代。老生代采用的回收算法是标记整理算法。(更详细的内容将后续文章详细介绍GC回收)方法区(Method Area)
方法区也称"永久代",它用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域。默认最小值为16MB,最大值为64MB(64位JVM由于指针膨胀,默认是85M),可以通过-XX:PermSize
和 -XX:MaxPermSize 参数限制方法区的大小。它是一片连续的堆空间,永久代的垃圾收集是和老年代(old
generation)捆绑在一起的,因此无论谁满了,都会触发永久代和老年代的垃圾收集。不过,一个明显的问题是,当JVM加载的类信息容量超过了参数-XX:MaxPermSize设定的值时,应用将会报OOM的错误。参数是通过-XX:PermSize和-XX:MaxPermSize来设定的运行时常量池(Runtime Constant Pool):是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种符号引用,这部分内容将在类加载后放到方法区的运行时常量池中。
从JDK7开始移除永久代(但并没有移除,还是存在),贮存在永久代的一部分数据已经转移到了Java Heap或者是Native Heap:符号引用(Symbols)转移到了native heap;字面量(interned strings)转移到了java
heap;类的静态变量(class statics)转移到了java
heap。从JDK8开始使用元空间(Metaspace),元空间的大小受本地内存限制,新参数(MaxMetaspaceSize)用于限制本地内存分配给类元数据的大小。如果没有指定这个参数,元空间会在运行时根据需要动态调整。具体的可以查看这篇文章:https://blog.youkuaiyun.com/zhushuai1221/article/details/52122880
(Java 8: 从永久代(PermGen)到元空间(Metaspace))3.虚拟机栈(JVM Stack)
描述的是java方法执行的内存模型:每个方法被执行的时候都会创建一个"栈帧",用于存储局部变量表(包括参数)、操作栈、方法出口等信息。每个方法被调用到执行完的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。声明周期与线程相同,是线程私有的。栈帧由三部分组成:局部变量区、操作数栈、帧数据区。局部变量区被组织为以一个字长为单位、从0开始计数的数组,和局部变量区一样,操作数栈也被组织成一个以字长为单位的数组。但和前者不同的是,它不是通过索引来访问的,而是通过入栈和出栈来访问的,可以看作为临时数据的存储区域。除了局部变量区和操作数栈外,java栈帧还需要一些数据来支持常量池解析、正常方法返回以及异常派发机制。这些数据都保存在java栈帧的帧数据区中。局部变量表: 存放了编译器可知的各种基本数据类型、对象引用(引用指针,并非对象本身),其中64位长度的long和double类型的数据会占用2个局部变量的空间,其余数据类型只占1个。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量是完全确定的,在运行期间栈帧不会改变局部变量表的大小空间。
4.本地方法栈(Native Stack)
与虚拟机栈基本类似,区别在于虚拟机栈为虚拟机执行的java方法服务,而本地方法栈则是为Native方法服务。(栈的空间大小远远小于堆)5.程序计数器(PC Register) 是最小的一块内存区域,它的作用是当前线程所执行的字节码的行号指示器,在虚拟机的模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、异常处理、线程恢复等基础功能都需要依赖计数器完成。
6.直接内存
直接内存并不是虚拟机内存的一部分,也不是Java虚拟机规范中定义的内存区域。jdk1.4中新加入的NIO,引入了通道与缓冲区的IO方式,它可以调用Native方法直接分配堆外内存,这个堆外内存就是本机内存,不会影响到堆内存的大小.
(掌握)数组常见异常
① NullPointerException:空指针异常(空引用异常)
② ArrayIndexOutOfBoundsException:数组索引越界异常
成员变量和局部变量
a.成员变量:直接定义在类中,方法外面。又称之为字段(Field)
b.局部变量:除了成员变量,其他都是局部变量,具体存在于:
1.方法的参数中
2.代码块中(一对花括号里面)
变量的初始值
成员变量:默认是有初始值的,不同类型的初始值如下图:
数据类型 默认初始化值
byte,short,int,long 0
float,double 0.0
char 一个空字符串(空格),即’\u0000’
boolean false
引用数据类型 null,表示不引用任何对象
变量的生命周期
变量的生命周期,表示变量能在内存中存活多久
成员变量:储存在堆内存中,随着对象的销毁而销毁
局部变量:储存在栈内存中,随着所定义方法的调用结束而销毁
局部变量储存在方法中,每次调用都会在栈空间开辟一块内存空间的调用
类与对象
类是对某一事务的抽象描述
对象是一个该类事务的个体
JavaBan规范
1.类用public修饰
2.字段用private修饰 如果字段是boolean类型 将getName改成isName
3.有get set 方法
如:
public boolean isSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
4.有无参构造器
(重点)private ,protected ,public ,default的区别
- public:具有最大访问权限,可以访问任何一个在classpath下的类、接口、异常等。简言之就是项目下所有包下的类都可以访问
- protected:主要作用是用来保护子类的,它的含义在于可以用它修饰的成员其他的不可以,它相当于传递给子类的一种继承的东西
- default:有时也称friendly,他是针对包访问而设计的,任何处于本包下的类、接口、异常等,都可以互相访问,即使是父类没有用protected修饰的成员也是可以的。
- private:访问权限仅限于类内部。
优先级:private<default<protected<public
内部类 本包 子类 外部包
public √ √ √ √
protected √ √ √ ×
default √ √ × ×
private √ × × ×
(掌握)重载、继承、重写、多态
1.重载的特点是:
在同一个类中,方法名相同,参数列表(参数类型,参数个数,参数顺序)不同
2.重写:
方法名和参数列表必须与被重写的方法相同。
重写方法的访问修饰符一定要大于被重写的方法的访问修饰符,并且不能为private(public>protected>default>private)
重写方法返回值一定要与被重写的方法返回值一样
静态方法不能被重写为非静态方法
3.多态
多态的好处:
A:提高了代码的维护性(继承保证)
B:提高了代码的扩展性(由多态保证 接口实现,方法复写。)
(消除类型之间的耦合关系。)
多态的缺陷:
不能使用子类的特有功能。
如果非要使用的话:怎么用呢?
A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)
B:把父类的引用强制转换为子类的引用。(向下转型)
多态经典实例:
//父类
public class Animal { //动物类
public void sleep(){
System.out.println("哪里都睡");
}
public void eat(){
System.out.println("什么都吃");
}
public static void main(String[] args) {
Animal a;
a=new Cat(); //创建猫对象
a.eat();
a.sleep();
a=new Dog(); //创建狗对象 通过父类new子对象 只能使用父类方法
a.sleep();
a.eat();
((Dog) a).swimming(); //若果非要调用子类特有的方法 可以向下转型
Dog d = new Dog();
Dog d2 = new Dog();
Dog d3 = new Dog();
a= (Dog) new Animal();//出现类型转换异常
System.out.println(a instanceof Animal);
a.sleep();
a.sleep();
//c.eat();
a.eat();//这是父类有的方法
a.sleep();//这是父类有的方法
((Dog) a).swimming();//这是子类dog中的独有的方法 正常无法调用
a.eat();
//这里狗实现了游泳的方法
AnimalUtils.getDog(d);
AnimalUtils.getDog(d2);
AnimalUtils.getDog(d3);
//这里狗没有实现游泳的方法
AnimalUtils.useAnimal(d);
AnimalUtils.useAnimal(d);
AnimalUtils.useAnimal(d);
}
}
//狗 子类 继承animal类
class Dog extends Animal{
public void sleep(){
System.out.println("狗趴着睡");
}
public void eat(){
System.out.println("狗吃骨头");
}
public void swimming(){
System.out.println("狗还会游泳");
}
}
//猫 子类 继承Animal类
class Cat extends Animal{
public void sleep(){
System.out.println("猫蜷缩着睡觉");
}
public void eat(){
System.out.println("猫吃鱼");
}
static class AnimalUtils{
private AnimalUtils(){};
public static void getDog(Dog d){
d.sleep();
d.eat();
d.swimming();
}
public static void getCat(Cat c){
c.sleep();
c.eat();
}
public static void useAnimal(Animal a) {
a.eat();
a.sleep();
}
}
}
4.继承
继承的好处 :
a:提高了代码的复用性
b:提高了代码的维护性,可扩展性(实现父类方法还可以继承其他接口)
c:让类与类之间产生了关系,是多态的前提
继承的缺点:
1.继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法;
2.降低代码的灵活性。子类必须拥有父类的属性和方法,让子类自由的世界中多了些约 束;
3.增强了耦合性。当父类的常量、变量和方法被修改时,需要考虑子类的修改,而且在 缺乏规范的环境下,这种修改可能带来非常糟糕的结果——大段的代码需要重构。缺陷:
(掌握)封装的作用
1.`
- 隔离性:
被封装后的对象(这里的对象是泛指代码的编程单元,一般指:程序集,命名空间,类,方法,属性,变量等)其外部对象是无法直接访问对象的内部实现细节,内部实现细节的的改动不会影响到外部对象的访问原则(即:对象内部修改后,在公开暴露指定的访问路径不变的情况下,外部访问它的对象是无需修改的),这是隔离性的体现,同时也是实现高内聚,低耦合的最根本的思想之一;
2.可复用性:
被封装后的对象可以被外部多个对象访问,而无需为每个外部对象去指定不同的服务对象;如:所有的对象的基类都是object类,object类里面的公共成员可以被其所有子类使用,Ado.Net相关的数据访问类及其公共成员均可被其它所有的对象使用等。
3.可读性:
被封装后的对象的名称(如:程序集名,类名,方法名)如果命名恰当,那么就能在不看里面的实现细节的前提下,了解该对象的作用;如:DataTable就是用来装表格数据的;ToString就是转换为字符串,Length就是指长度等。
Static修饰符
Static特点:
1.使用static修饰的字段和方法直接属于类,不属于该改类的对象。字段和方法属于谁就让谁调用。
2.使用static修饰的成员:属于类 直接使用类名调用即可
3.没有static修饰的成员属于对象,必须先创建再调用。
4.Static没有super()和this()方法
内存分析:static修饰的成员变量(字段),随着所在类被加载进JVM,也同时存储在方法区中,被锁有对象共享。
final修饰符特点:
1.Final修饰的类:表示最终的类不能再有子类
2.Final修饰的方法:表示最终的方法,该方法不能被子类覆盖
3.Final修饰的变量:表示常量,该变量只能被赋值一次,不能再重新赋值
1)基本引用类型:表示值不能改变
2)引用数据类型:所引用的的地址值不能改变(如数组中的元素可以改变值不可以改变地址)
匿名内部类
装箱拆箱(实例 :String和Integer和int之间的相互转换
)
public class Demo {
public static void main(String[] args) {
//装箱
Integer a=new Integer("12");
System.out.println(a);//12
//拆箱
int b=a.intValue();
System.out.println(b);//12
String str="123";
//String转Integer
Integer c=Integer.parseInt(str);
System.out.println(c);//123
//过程中包函了自动拆箱
//String转int
int d=Integer.parseInt(str);
System.out.println(d);//123
//int 转String
String str1=b+"";
System.out.println(str1);//12
//Integer转String
String str2=a.toString();
System.out.println(str2);//12
}
}
日期与字符串之间的转换:
String str=”2017-06-09
SimpleDateFormat sdf=new SimpleDateFormat(“yyyy-MM-dd”);
Date d=sdf.prase(str);
String s=sdf.format(d);
Calendar 日历类
CalendarCalendar c=Calendar.getInstance();
c.setTime(d);//把当前输入时间转换为Calendar对象
c.getTime()
;
常见异常体系:
Throw 与throws
1.throws:使用在方法声明上,提醒方法调用者需要处理异常
2.Throw:用于返回一个错误结果,抛出一个具体异常类的对象给调用者
异常体系分为(checked)编译异常和(runtime)运行异常
RuntimeException其子类属于运行异常,其他属于编译异常
编译异常编译时期即可检测出,必须要求处理;运行异常编译时期不被检测,只有运行是才会被检查出来。
运行异常可以由程序员主动规避。
自定义异常(类的继承):
public class MyException extends Exception{
public MyException(String message) {
super(message);
}
}
StringBuilder 和StringBuff 和String区别
String 是不可变的每次内容改变都会在内存中开辟新空间,性能很低,不建议使用
StringBuilder与StringBuffer之间的区别在于StringBuilder是线程不安全的;而StringBuffer是线程安全的,其他都一样。
用法:
StringBuilder sb=new StringBuilder();
for(int i=0;i<10;i++){
Sb.append(i);
}
String str=Sb.toString();
System.out.println(str);
Random用法
Random类用于产生一个伪随机类
Random r=new Random();
Int n=R.nextInt(100);//100以内的随机数
UUID
表示通用唯一标识符 缺点:生成的字符串太长
用法:
String uuid=UUID.randomUUID().toString;
System.out.println(uuid);
BigDecimal的使用(用于表示精确的小数位数)
public class BigDecimalDemo {
static BigDecimal b1=new BigDecimal("12.3");
static BigDecimal b2=new BigDecimal("3.0");
//加法
BigDecimal b3=b1.add(b2);
//乘法
BigDecimal b5=b1.multiply(b2);
//减法
BigDecimal b6=b1.subtract(b2);
static //除法 保留小数位数,并设置数据舍入格式
BigDecimal b7=b1.divide(b2, RoundingMode.HALF_UP);
public static void main(String[] args) {
//BigDecimal转基本数据类型
System.out.println(b7);
}
}
启动线程的两种方式(重点 掌握)
1.继承、thread类
2.实现runnable接口
代码:
public class ThreadDemo extends Thread{
@Override
public void run(){
for(int i=0;i<100;i++){
System.out.println(i);
}
}
}
public static void main(String args[]){
ThreadDemo t1=new ThreadDemo ();
t1.start();
}
public class ThreadDemo implements Runnable{
@Override
public void run(){
for(int i=0;i<100;i++){
System.out.println(i);
}
}
public static void main(String args){
}
}
保证线程安全的两种写法:
public class TestDemo{
Apple a=new Apple();
new Thread(a,”A”).start;
new Thread(b,”B”).start;
new Thread(c,”C”).start;
}
class Apple implements Runnable{
int num=100;
@Override
public void run(){
While(num>0){
Try{
Threab.sleep(1000);
Synchronized(this)
if(num>0){
System.out.println(Thread.currentThread.getName()+”吃掉了第”+num+”个苹果”);
Num--;
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
数组的性能分析(了解):
ArrayList(数组) 做查询和修改是非常快的 但新增和删除较慢
LinkedList (链表) 做查询和修改较慢 但新增和删除是非常快的(稍多加了解)
Queue 队列 擅长操作头和尾
hashMap 数组和链表的集合 擅长操作等值查询(equals比较)(稍多加了解)
数和二叉树
容器的分析
List(列表):允许记录添加顺序,允许元素重复。
Set(集合):不记录添加顺序,不允许元素重复
Map(映射):容器中没一个元素都包含一对key和value,key不允许重复,value可以重复。严格上说,并不是容器(集合),是两个容器中元素映射关系
List 与 Set 接口继承于Collection接口,Map接口不继承Collection接口
面试题:Vector Stack LinkedList区别
1.Vector 线程安全,效率低,其实就是古老的ArrayList,数组实现
2.Stack 后进先出 (类似于手枪填弹过程);是Vector子类;擅长操作栈顶,有自己特殊的方法
(注意:我们用的容器接口或类都处于java.util包中)
3.LinkedList是数组与链表的集合(记住这个就可以了)
List,Map,Set集合的遍历(重点)
List有for循环遍历,迭代遍历,foreach遍历
Map有迭代遍历,foreach遍历
Set有迭代遍历,foreach遍历
NO1>>>>>
List<String> list = new ArrayList<String>();
list.add("张三");
list.add("李四");
list.add("王五");
//1、这种方法效率最高,经常使用
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//2、通过迭代器迭代遍历
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
3、利用foreach循环遍历
for(String data : list){
System.out.println(data);
}
NO2>>>>>>>>>
Set<String> set = new HashSet<String>();
set.add("zhangsan");
set.add("lisi");
set.add("wanwu");
//1、利用迭代器迭代遍历
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
//2、foreach循环遍历
for (String data : set) {
System.out.println(data);
}
NO3>>>>>>>>>
Map<String, String> map = new HashMap<String, String>();
map.put("name", "lili");
map.put("age", "10");
//1、通过keyset二次取值,比较经常使用
for (String key : map.keySet()) {
System.out.println(key + map.get(key));
}
//2、通过entrySet使用迭代器遍历key和value
Iterator<Map.Entry<String,String>>iterator=map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
System.out.println(entry.getKey() + entry.getValue());
}
//3、通过Map.entrySet遍历key和value(推荐容量大时使用)
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + entry.getValue());
}
//4、通过Map.values()遍历所有的value,但不能遍历key
for (String value : map.values()) {
System.out.println(value);
}
Collections(掌握部分实用方法)
> public class CollectionsDemo {
>
> public static void main(String[] args){ //1.0 Arrays
> //数组转列表 List<String> list = Arrays.asList("Larry", "Moe", "Curly"); System.out.println(list);
> //转字符串 char[] k = { 'a', 'f', 'b', 'c', 'e', 'A', 'C', 'B' }; System.out.println(Arrays.toString(k));// [a, f, b, c, e, A, C, B]
> //copyOf int[] h = { 1, 2, 3, 3, 3, 3, 6, 6, 6, };
> //从列表中拷贝前n个数据到新的数组中 int i[] = Arrays.copyOf(h,h.length); for (int j : i) { System.out.print(j); } // 换行
> System.out.println();
> // copyOfRange将指定数组的指定范围复制到新数组中 int j[] = Arrays.copyOfRange(h, 6, 11); System.out.println("Arrays.copyOfRange(h, 6, 11):");
> // 输出结果66600(h数组只有9个元素这里是从索引6到索引11复制所以不足的就为0) for (int j2 : j) { System.out.print(j2); } // 换行 System.out.println(); //2.0
> Collections
> //集合反转 Collections.reverse(list); System.out.println(list);
> // void sort(List list),按自然排序的升序排序 Collections.sort(list); System.out.println("Collections.sort(arrayList):");
> System.out.println(list);
> // void swap(List list, int i , int j),交换两个索引位置的元素 Collections.swap(list, 0,1);
> System.out.println("Collections.swap(arrayList, 0, 1):");
> System.out.println(list);
> // 定制排序的用法 Collections.sort(list, new Comparator<String>() { @Override public int compare(String o1, String o2) {
> return (o2).compareTo(o1); } }); System.out.println("定制排序后:"); System.out.println(list);
> //Collection查找,替换操作 ArrayList<Integer> arrayList = new ArrayList<Integer>(); arrayList.add(-1); arrayList.add(3);
> arrayList.add(3); arrayList.add(-5); arrayList.add(7);
> arrayList.add(4); arrayList.add(-9); arrayList.add(-7);
> ArrayList<Integer> arrayList2 = new ArrayList<Integer>();
> arrayList2.add(-3); arrayList2.add(-5); arrayList2.add(7);
> System.out.println("原始数组:"); System.out.println(arrayList);
> //找出list中的最大值 System.out.println("Collections.max(arrayList):");
> System.out.println(Collections.max(arrayList)); //找出list中的最小值
> System.out.println("Collections.min(arrayList):");
> System.out.println(Collections.min(arrayList));
> System.out.println("Collections.replaceAll(arrayList, 3, -3):"); Collections.replaceAll(arrayList, 3, -3);
> System.out.println(arrayList);
>
> //int frequency(Collection c, Object o)//统计元素出现次数
> System.out.println("Collections.frequency(arrayList, -3):");
> System.out.println(Collections.frequency(arrayList, -3));//找出了-3出现个数
>
> //int indexOfSubList(List list, List
> target)//统计target在list中第一次出现的索引,找不到则返回-1,类比int lastIndexOfSubList(List
> source, list target).
> System.out.println("Collections.indexOfSubList(arrayList,
> arrayList2):");
> System.out.println(Collections.indexOfSubList(arrayList,
> arrayList2));
>
> System.out.println("Collections.binarySearch(arrayList, 7):"); //
> 对List进行二分查找,返回索引,List必须是有序的 Collections.sort(arrayList);
> System.out.println(Collections.binarySearch(arrayList, 7)); } }
IO
## 1.掌握File类常用方法(重点)
序号 方法 返回类型 说明
1 getName() String 获取文件名称
2 canRead() boolean 判断File是否可读,可读返回true
3 canWrite() boolean 判断File是否可写,可写返回true
4 exists() boolean 判断File是否存在,存在返回true
5 length() long 获取File长度
6 getAbsolutePath() String 获取File绝对路径
7 getParent() String 获取File父目录
8 isFile(); boolean 判断File是否是文件,是文件返回true
9 isDirectory() boolean 判断File是否是目录,是目录返回true
10 isHidden() boolean 判断File是否是隐藏文件,是返回true
11 lastModified() long 获取文件最后修改时间,时间是从1970 年午夜至最后修改时刻的毫秒数
12 mkdir() boolean 创建目录,如果创建成功返回true,如果目录存在则不创建,并返回false
11 list() String[] 返回目录下的所有文件名
12 listFiles() File[] 返回目录下的全部文件对象
13 list(FilenameFilter filter) String[] 返回目录下的所有文件名(filter用于指定过滤文件的类型)
14 listFiles(FilenameFilter filter) File() 返回目录下的所有文件对象(filter用于指定过滤文件的类型)
2.掌握字节输入输出流
public String getString() throws IOException{
String path="D:/calcCharNum.txt";
File file=new File(path);
//如果文本文件不存在则创建
if(!file.exists()){
file.createNewFile();
}
//使用FileOutputStream向文本写入数据
FileOutputStream output=new FileOutputStream(file);
output.write("AEBFFDFFFBDEEBCCBBCDADCDDFF".getBytes());
//使用FileInputStream读取文本文件信息
FileInputStream input=new FileInputStream(file);
//创建大小为10缓冲区
StringBuilder sb=new StringBuilder();
byte[] by=new byte[10];
int len;
while((len=input.read(by))!=-1){
sb.append(new String(by,0,len));
//len=input.read(by);
}
output.close();
input.close();
String str=sb.toString();
return str;
}
3.掌握缓冲流用法(重点)(文件复制)
public class TestBufferIO {
public static void main(String[] args) {
// 使用缓冲字节流实现复制
long time1 = System.currentTimeMillis();
copyFile1("d:book.txt", "d:booked.txt");
long time2 = System.currentTimeMillis();
System.out.println("缓冲字节流花费的时间为:" + (time2 - time1));
}
/**
* 缓冲字节流实现的文件复制的方法
*/
static void copyFile1(String src, String dec) {
// 声明读的文件字节流,与缓冲流
FileInputStream fis = null;
BufferedInputStream bis = null;
// 声明写的文件字节流,与缓冲流
FileOutputStream fos = null;
BufferedOutputStream bos = null;
int temp = 0;
try {
fis = new FileInputStream(src);
fos = new FileOutputStream(dec);
//使用缓冲字节流包装文件字节流,增加缓冲功能,提高效率
//缓存区的大小(缓存数组的长度)默认是8192,也可以自己指定大小
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
while ((temp = bis.read()) != -1) {
bos.write(temp);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//注意:增加处理流后,注意流的关闭顺序!“后开的先关闭!”
try {
if (bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bis != null) {
bis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
上述代码可简写为:
/**
* 缓冲字节流实现的文件复制的方法
*/
static void copyFile1(String src, String dec) {
int temp = 0;
try(
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos= new FileOutputStream(dec);
//使用缓冲字节流包装文件字节流,增加缓冲功能,提高效率
//缓存区的大小(缓存数组的长度)默认是8192,也可以自己指定大小
BufferedInputStream bis= new BufferedInputStream(fis);
BufferedOutputStream bos= new BufferedOutputStream(fos);
){
while ((temp = bis.read()) != -1) {
bos.write(temp);
}
}catch(Exception e){
e.printStackTrace();
}
}
}