java基础知识点整理(四)

1、关于java中的数组

1.java语言中的数组是一种引用数据类型,不属于基本数据类型。数组的父类是Object类。
2.数组实际上是一个容器,可以同时容纳多个元素。(数组是一个数据的集合),数组:字面意思是“一组数据”。
3.数组当中可以存储基本数据类型的数据,也可以存储引用数据类型的数据。
4.数组因为是引用数据类型,所以数组对象是在堆内存当中。(数组是存储在堆内存当中的)
5.对于数组当中如果存储的是java对象的话,实际上存储的是对象的引用(内存地址)。
6.数组一旦创建,在java中规定,长度不可变。(数组的长度不变)
7.数组的分类:一维数组,二维数组…(一维数组较多,二维数组偶尔使用)
8.所有的数组对象都有length属性(java自带的),用来获取数组中元素的个数。
9.java中的数组要求数组中存储的元素类型统一。比如int类型数组只能装int类型数据,Person数组只能存储Person类型数据。
10.数组在内存方面存储的时候,数组中的元素内存地址是连续的(存储的每一个元素都是有规则的挨着排列的内存地址连续),这是数组存储的 特点。数组实际上是一种简单的数据结构。
11.所有的数组都是拿“第一个小方框的地址”作为整个数组对象的内存地址。(数组中首元素的内存地址作为整个数组对象的地址)
12.数组中每一个元素都是有下标的,下标才能够0开始,以1递增,最后一个元素的下标是length-1.
下标非常重要,因为我们对数组中元素进行“获取”的时候,都是通过下标来进行的。
13.数组这种数据结构的优点和缺点是什么??
优点:查询/检索某个下标的元素时效率很高,可以说是查询效率 最高的一种数据结构。
为什么查询效率高?
第一:每一个元素的内存地址在空间存储上是连续的。
第二:每一个元素的类型相同,所以占用空间内存大小一样。
第三:知道第一个元素的内存地址,知道一个元素占用空间的大小,又知道下标,所以通过一个数学表达式就可以计算某个下标上元素的内存地址。直接通过内存地址定位元素,所以数组的检索效率最高。
缺点
第一:由于为了保证数组中每个元素的内存地址连续,所以在数组上随机删除或者增加元素的时候,效率较低,因为增删元素会涉及到后面的元素统一向后面移位的操作。
第二:数组不能存储大数据量。为什么?因为很难在内存上找到一块大的连续内存空间。
注意:对于数组中最后一个元素的增删,是没有效率影响的。

2、在java开发中,数组长度一旦确定不可变,那么数组满了怎么办?

数组满了,需要扩容。
Java中对数组的扩容:
先新建一个大容量的数组,然后将小容量的数组一个一个拷贝到大数组中。
结论:数组扩容效率较低,因为涉及到拷贝问题。所以在以后的开发中请注意:尽可能少的进行数组拷贝。可以在创建数组的时候预估一下多长合适,最好预估准确,这样可以减少数组的扩容次数,提高效率。

3、java中的数组怎么进行拷贝?

调用JDK System类中的arraycopy()方法,来完成数组拷贝。
数组中如果存储的元素是引用,可以拷贝吗?当然可以。

4、编写程序,使用一维数组,模拟数据结构。

要求:
1.这个栈可以存储java中任何一个引用数据类型的数据。
2.在栈中提供push方法模拟压栈(栈满了,要有提示信息)
3.在栈中提供pop方法模拟弹栈(栈空了,也要有提示信息)
4.编写测试程序,new栈对象,调用push和pop方法类模拟压栈弹栈的动作。

public class MyStack {
	//提供一个数组来存储栈中元素
	//Object[]这是一个万能的口袋,这个口袋可以装任何引用数据类型的数据
	//为什么选择Object类型数组?因为这个栈可以存储java中的任何引用数据类型
    private Object[] elements;
    //栈帧(永远指向栈顶部元素)
    //每加一个元素,栈帧加一;每减一个元素,栈帧减一
    //那么这个默认初始值应该是多少?注意,最初的栈是空,一个元素都没有
    //如果index采用0,表示栈帧指向了顶部元素的上方 
    //如果index采用-1,表示栈帧指向了顶部元素
    private int index;

	//get和set方法也许用不上,但是必须写上,这是规矩,表示存储到数组中
	//封装:第一步:属性私有化;第二步:对外提供get和set方法
    public Object[] getElements() {
        return elements;
    }
    public void setElements(Object[] elements) {
        this.elements = elements;
    }
    public int getIndex() {
        return index;
    }
    public void setIndex(int index) {
        this.index = index;
    }

	//构造方法 
	//构造方法中给一维数组一个初始化容量
    public MyStack() {
    	//默认初始化为10
        this.elements = new Object[10];
        //给index初始化
        this.index=-1;
    }

	//push方法,压栈,表示栈中多一个元素,但是如果栈已满,压栈失败
    public void push(Object ele){
        if(index >= elements.length -1){
            System.out.println("栈已满,压栈失败!");
            return;
        }
        //程序走到这里说明栈没满
        //向栈中加一个元素,栈帧向上移动一个位置
        elements[++index] = ele;
        System.out.println("压栈"+ele+"成功,栈帧指向"+this.index);
    }

	//pop方法,弹栈,表示栈中少一个元素,但是栈如果已空,弹栈失败
	//弹栈方法,从数组中取元素,栈帧向下移位
    public void pop(){
        if (index < 0){
            System.out.println("栈为空,弹栈失败!");
            return;
        }
        System.out.println("弹栈"+elements[index]+"元素成功");
        index--;
        System.out.println("栈帧指向"+index);
    }
}

5、冒泡排序

for(int i=arr.length-1;i>0;i--){
	for(int j=0;j<i;j++){
		if(arr[j] > arr[j+1]){
			int temp;
			temp=arr[j];
			arr[j]=arr[j+1];
			arr[j+1]=temp;
		}
	}
}

6、选择排序

每一次选择这堆“参与比较的数据当中”找出最小值,拿着这个最小值和“参与比较这堆数据最前面的元素”交换位置。选择排序比冒泡排序好在:每一次的交换位置都是有意义的。
选择排序比冒泡排序效率高。高在交换位置上。

for(int i=0; i<arr.length-1;i++){
	int min=i;
	for(int j=i+1;j<arr.length;j++){
		if(arr[j]<arr[min]){
			min=j;
		}
	}
	if(min != i){
		int temp;
		temp = arr[min];
		arr[min] = arr[i];
		arr[i] = temp;
	}
}

冒泡排序和选择排序比较次数没变,交换次数减少了。

7、二分法查找(折半查找)

二分法查找是基于排序的基础上查找,(没有排序的数组是无法查找的)
二分法查找的终止条件:一直折半,直到中间那个元素恰好是查找的元素。

private static int binarySearch(int[] arr, int dest){
	int begin=0;
	int end=arr.length;
	while(begin<=end){
		int mid=(begin+end)/2;
		if(arr[mid] == dest){
			return mid;
		}else if(arr[mid]<dest){
			begin = mid+1;
		}else{
			end = mid-1;
		}
	}
	return -1;
}

8、关于java JDK中内置的一个类:java.lang.String

1.String表示字符串类型,属于引用数据类型,不属于基本数据类型
2.在java中随便使用双引号括起来的都是String对象,例如:“abc”,“hello”…
3.java中规定,双引号括起来的字符串,是不可变的,也就是说“abc”自出生到死亡,不可变,不会变成“abcd”。
4.在JDK当中双引号括起来的字符串,例如“abc”是直接存储在“方法区”的“字符串常量池”中。
为什么SUN公司把字符串存储在一个字符串常量池当中呢?
因为字符串在实际开发中使用太频繁,为了执行效率,所以把字符串放到了方法区的字符串常量池当中。

9、面试题:判断数组长度和判断字符串长度不一样

判断数组长度是length属性,判断字符串长度是Length()方法。

10、我们在实际开发中,如果需要进行字符串的频繁拼接,会有什么问题?

因为java中的字符串长度是不可变的,每一次拼接都会产生新的字符串,这样会占用大量的方法区内存,造成内存空间的浪费。

11、关于StringBuffer和StringBuilder

StringBuffer底层实际上是一个byte[]数组,往StringBuffer中放字符串,实际上是放到byte数组当中了。StringBuffer的初始化容量是16。

//创建一个初始化容量为16的byte[]数组(字符串缓冲对象)
StringBuffer strBuffer = new StringBuffer();
//拼接字符串,以后拼接字符串统一调用append()方法
//append()是追加的意思
//append()方法底层在进行追加的时候,如果byte满了,会自动扩容
strBuffer.append("a");

如何优化StringBuffer的性能?
在创建StringBuffer的时候尽可能给定一个初始化容量。最好减少底层数组的扩容次数。预估一下,给一个大一些的初始化容量。
关键点:给一个合适的初始化容量。

StringBuffer和StringBuilder的区别?
StringBuffer中的方法都有:synchronized关键字修饰,表示StringBuffer在多线程环境下运行是安全的。
StringBuilder中的方法都没有:synchronized关键字修饰,表示StringBuilder在多线程环境下运行是不安全的。

12、包装类

1.java为八种基本数据类型又准备了八种包装类型。八种包装类型属于引用数据类型,父类是Object。
2.为什么要再提供八种包装类型?
因为八种基本数据类型不够用,所以SUN又提供了八种包装类。
3.八种基本数据类型对应的包装类型名

基本数据类型包装类型
bytejava.lang.Byte(父类Number)
shortjava.lang.Short(父类Number)
intjava.lang.Integer(父类Number)
longjava.lang.Long(父类Number)
floatjava.lang.Float(父类Number)
doublejava.lang.Double(父类Number)
booleanjava.lang.Boolean(父类Object)
charjava.lang.Character(父类Object)

以上八种包装类,重点以java.lang.Integer为代表学习,其他类照葫芦画瓢

13、面试题:String为什么是不可变的?

我看过源码,String类中有一个byte[]数组,这个byte[]数组采用final修饰。因为数组一旦创建长度不可变,并且final修饰的引用,一旦指向某个对象之后,不再指向其他对象。所以String是不可变的。

14、StringBuilder/StringBuffer为什么是可变的?

我看过源码,StringBuilder/StringBuffer内部实际上是一个byte[]数组,这个byte[]数组没有被final修饰,StringBuffer/StringBuilder的初始化容量是16,当内存满了之后会进行扩容,底层调用了数组拷贝的方法,System.arraycopy()…是这样扩容,所以StringBuffer/StringBuilder时候于字符串频繁拼接的操作。

15、自动装箱和自动拆箱

在java5之后引入的新特性。
自动装箱:基本数据类型自动转换成包装类
自动拆箱:包装类自动转换成基本数据类型。
自动装箱和自动拆箱的好处:方便编程。
“==”比较的是对象的内存地址,不会触发自动拆箱机制(只有±*/等运算的时候才会)
java中为了提高程序的效率,将[-128,127]之间的所有包装对象提前创建好,放到一个方法区的“整数常量池”当中,目的是只要用这个区间的数据就不需要new了,直接从整数型常量池中取出来。

Integer x=100;//x里面并不是保存100,保存的是100这个对象的内存地址
Integer y=100;
System.out.println(x==y);//true

Integer x=128;
Integer y=128;
System.out.println(x==y);//false

Integer类加载的时候,会初始化整数型常量池:256个对象。
池:cache,其实就是缓存机制。
缓存优点:效率高
缓存缺点:耗费内存
缓存机制要重视,大型项目中的重要优化手段就是:cache机制。、

16、Integer,String,int三种类型互相转换

三种类型互相转换

17、java中对时间的处理

1.获取系统当前时间(精确到毫秒的系统当前时间)
直接 调用无参数构造方法:
Date nowTime = new Date();

2.日期可以格式化吗?
将日期类型Date,按照指定的格式进行转换:Date–转换成具有一个格式日期字符串–>String
SimpleDateFormat是java.text包下的,专门负责日期格式化。
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss SSS”);
SimpleDateFormat sdf1 = new SimpleDateFormat(“yyyy/MM/dd HH:mm:ss SSS”);
String nowTimeStr = sdf.format(nowTime);
String nowTimeStr1 = sdf.format(nowTime);

3.将一个日期字符串String转换成Date类型
String time=“2008-08-08 08:08:08 888”;
SimpleDateFormat sdf2 = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss SSS”);
Date dateTime = sdf2.parse(time);

4.获取自1970年1月1日 00:00:00到当前系统时间的总毫秒数
long begin = System.currentTimeMillis();

18、数字格式化

java.text.DecimalFormat专门负责数字格式化。
###,###.##表示加入千分位,保留两个小数
###,###.0000表示加入千分位,保留4个小数,不够补0
DecimalFormat df = new DecimalFormat(“数字格式化”);

BigDecimal属于大数据,精度极高。不属于基本数据类型,属于java对象(引用数据类型),这是SUN提供的一个类,专门用在财务软件当中。

19、随机数

创建随机数对象
Random random= new Random();
随机产生一个int类型取值范围内的数字
int num1 = random.nextInt();
产生[1-100]之间的随机数,不能产生101
nextInt翻译为:下一个int类型的数据是101,表示只能取100
int num2 = random.nextInt(101);

20、枚举

1.枚举也是一种引用数据类型。
2.枚举编译之后也是.class文件。
3.枚举的定义:
enum 枚举类型名{枚举值1,枚举值2…}
4.结果只有两种情况,建议使用布尔类型;结果超过两种并且可以一一枚举出来,建议使用枚举。
5.switch语句 支持枚举类型,switch也支持String、int、
低版本的JDK只支持int
高版本的JDK支持Int,String,枚举,byte,short,char因为存在自动类型转换。

21、异常

1.什么是异常,java提供异常处理机制有什么用?
程序执行过程中出现的不正常情况。

2.异常的作用:增强程序的健壮性。
java语言是很完善的语言,提供了异常处理方式。程序在执行过程中出现了不正常的情况,java把该异常信息打印输出到控制台,供程序员参考。程序员看到异常信息之后,可以对程序进行修改,让程序更加健壮。

3.java语言当中异常是以什么形式存在的呢?
异常在java中以类的形式存在,每一个异常都可以创建异常对象。

4.java异常处理机制
Object下有Throwable(可抛出的)
Throwable下有两个分支:Error(不可处理,直接退出JVM)和Exception(可处理的)
Exception下有两个分支:
Exception的直接子类:编译时异常(要求程序员在编写程序阶段预先对这些异常进行处理,如果不处理编译器报错,因此得名:编译异常)
RunTimeException:运行时异常(在编写程序阶段程序员可以预先处理,也可以不管)
错误,还是异常都是可以抛出的。
所有的错误只要发生,java程序只有一个结果那就是终止程序的执行,退出JVM,错误是不能处理的。
所有的RunTimeException及其子类都属于运行时异常。运行时异常在编写阶段,你可以选择处理,也可以选择不处理。运行时异常还有另外一个名字:未受检异常或者非受控异常UnCheckedException。
所有Exception的直接子类都叫做编译时异常。编译时异常在编译阶段发生的吗?不是,编译时异常表示必须在编写程序的时候预先对这种异常进行处理,如果不处理,编译器报错。编译时异常发生概率较高。编译时异常又被称为受检异常,还有叫做受控异常CheckedException。
编译时异常和运行时异常,都是发生在运行阶段。编译阶段异常是不会发生的。

5.编译时异常因为什么而得名?
因为编译时异常必须编译(编写)阶段预选处理,如果不处理编译器报错,因此得名。所有的异常都是发生在运行阶段,因为只有运行阶段才能new对象,因为异常的发生就是在new对象

6.编译时异常和运行时异常的区别
编译时异常一般发生的概率比较高。
运行时异常一般发生的概率比较低。

7.java语言中对异常的处理包括两种方式
第一种方式:在方法声明的位置上,使用throws关键字,抛给上一级
谁调用我,我就抛给谁。类似于推卸责任。
第二种方式:使用try…catch语句进行异常捕捉。
这件事发生了,谁都不知道,因为我给抓住了。异常真正解决。

注意:只要异常没有捕捉,采用上报的方式,此方法的后续代码不会执行。另外需要注意,try语句块中某一行出现异常,该行后面的代码不会执行。try…catch捕捉之后,后续代码会执行。

8.在以后的开发中,处理编译时异常,应该上报还是捕捉呢?怎么选?
如果希望调用者来处理,选择throws上报。
其余捕捉。

9.异常对象的两个方法:getMessage,printStackTrace
//这里只是new了异常对象,但是没有将异常对象抛出,JVM会认为这是一个普通的java对象。
NullPointerException exception = new NullPointerException(“空指针异常!”);
获取异常简单的描述信息,这个信息实际上就是构造方法上面String参数:
String msg = exception.getMessage();
打印异常追踪的堆栈信息,java在后台打印异常堆栈追踪信息的时候,采用异步线程的方式打印:
exception.printStackTrace();

10.我们以后查看异常的追踪信息,应该怎么看可以快速的调试程序呢?
异常追踪信息从上往下一行一行看,注意的是SUN公司写的代码不需要看,主要看自己写的代码。

11.java中怎么自定义异常?
两步:
第一步:编写一个类继承Exception或者RunTimeException
第二步:提供两个构造方法,一个无参数的,一个带有String参数的。
举例:编写一个栈操作异常

public class MyStackOperatorException extends Exception{
	public MyStackOperatorException(){}
	public MystackOperatorException(String s){
		super(s);
	}
}
//创建异常对象
MyStackOperatorException e = new MyStackOperatorException("栈已满,压栈失败!");
//**手动将异常抛出去**
throw e;//这里捕捉没有意义,自己new一个异常自己捉,没有意义。
//栈已满这个信息你需要传递出去

//将以上两段代码合并,手动抛异常
throw new MyStackOperatorException("栈已满,压栈失败!");

重点:自定义异常在开发中的应用!

22、关于try…catch中的finally子句

1.在finally子句中的代码是最后执行的,并且一定会执行,即使try语句块中的代码出现了异常。
finally子句必须和try一起出现,不能单独编写。
2.finally语句通常使用在哪些情况下呢?
通常在finally语句块中完成资源的释放/关闭。
因为finally中的代码比较有保障,即使try语句块的代码出现异常,finally也会正常执行。
3.try和finally,没有catch可以吗?可以
try不可以单独使用,try和finally可以联合使用。
以下代码执行顺序是:
先执行try
再执行finally
最后再执行return;(return语句只要执行,方法必然结束)

try{
	System.out.println();
	return;
}finally{
	System.out.println();
}

4.退出JVM之后,finally语句中的代码就不执行了。
System.exit(0);//退出JVM

23、final、finally、finalize有什么区别?

final关键字:
final修饰的类无法继承
final修饰的方法无法覆盖
final修饰的变量不能重新赋值
finally关键字:
和try一起使用
finally语句块中的代码一定会执行
finalize标识符:
是一个Object类中的方法名,这个方法是由垃圾回收器GC负责调用的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值