提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
NullPointerException 空指针异常 -NPE
当程序运行中,试图在需要对象的地方使用某一个对象时,发现对象为 null ,此时抛出该异常。以下这几种情况会发生空指针异常:
调用 null 对象的实例方法。
访问或修改 null 对象的字段。
将 null 作为一个数组,获得其长度。
可以在代码中写if判断他是否为空来避免。比如下面的代码:
public static int sum(){
//遍历数组,累加所有元素
int sum = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] != null)
sum = sum + arr[i];
}
System.out.println("arr元素的累加和:"+sum);
return sum;
}
同时在Java 8的类库中有Optional类;
当你使用指针进行操作的时候,如果不确定指针是否为null应该对指针做非空判断,判断指针为null时,使用new关键字开辟内存空间if(指针== null) {指针= new …}
1.用于在堆区造数组
new 数据类型[长度]
数组的构造器是系统默认就有的,任何一种数据类型都
可以使用数组构造器来构造数组。
例如: new int[10]
2.用于在堆区造对象
new 构造方法()
对象的构造器是类里面提供的
例如:new Student();
这个new后面的Student()是一个方法,是编译器给你自动生成的,
在字节码文件中可以看到他,
区别在于数组里装的东西不一样,一个是基本类型,一个是对象。
对象本身是引用数据类型,对象创建在堆中,而对象变量存放在栈中,对象变量中存放的是对象的引用地址。
Java中的基本数据类型只有8个:byte(1字节)、short(2字节)、int(4字节)、long(8字节)、float(4字节)、double(8字节)、char(1字节)、boolean。
对应的包装类分别是:Byte、Short、Integer、Long、Float、Double、Character、Boolean。
正序遍历
public static void iterator(){
//正向遍历都是从0开始的(因为数组的索引都是从0开始的)
//到arr.length结束,length是数组的长度
//循环变量i只能 < length.不能<=length,或者<=length-1
for (int i = 0; i < arr.length; i++)
{
if (arr[i] != null)
System.out.print(arr[i]+" ");
else
break;
}
}
逆序遍历
public static void reversa(){
for(int i = arr.length-1; i >= 0 ; i--)
System.out.print(arr[i]+" ");
}
public static void sum(){
//遍历数组,累加所有元素
int sum = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] != null)
sum = sum + arr[i];
}
System.out.println("arr元素的累加和:"+sum);
}
最大值:
public static void max(){
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if(arr[i] != null && arr[i] > max)
max = arr[i];
}
System.out.println("arr元素中最大的值是"+max);
}
最小值:
public static void min(){
int min = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] != null && arr[i] < min)
min = arr[i];
}
System.out.println("arr数组中最小值是:"+ min);
}
public static void avg(){
int sum = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] != null)
sum = sum + arr[i];
}
System.out.println("arr元素的平均值:" + (double)sum/arr.length);
}
public static void dilatation(){
//数组是一种定长的数据结构
//数组扩容的策略:1、创建新数组,2、把原数组的元素转移到新数组,3把新数组的地址赋值给原数组
Integer[] newarr =new Integer[arr.length * 2];
for (int i = 0; i < arr.length; i++){
newarr[i] = arr[i];
}
arr = newarr;
}
public static void insert(int insertIndex,int e){ //需要插入的索引
//在数组中的指定位置插入一个元素,并且不会堆其他元素造成影响
//例如:在arr[5]的位置插入33
//arr[5] = 33;这样写不是插入,而是覆盖
int temp = -1; //记录第一个为空的索引
for (int i = 0; i < arr.length; i++) {
if (arr[i] == null) {
temp = i;
break;
}
}
for (int i = temp; i > insertIndex; i--) {
arr[i] = arr[i-1];
}
arr[insertIndex] = e;
System.out.print("在arr[5]插入33:");
iterator();
}
public static void remove(int rem){
for (int i = rem; arr[i] != null; i++) {
arr[i] = arr[i+1];
}
System.out.print("\n删除第"+rem+"位的元素:");
iterator();
}
public static void reversal() {
int temp = -1; //记录第一个为空的索引
for (int i = 0; i < arr.length; i++) {
if (arr[i] == null) {
temp = i;
break;
}
}
Integer swap;
for (int i = 0;i < temp/2; i++){
swap = arr[i];
arr[i] = arr[temp-1-i];
arr[temp-1-i] =swap;
}
System.out.print("\n逆序输出:");
iterator();
}
public static void bubbling(){
int temp = -1; //记录第一个为空的索引
for (int i = 0; i < arr.length; i++) {
if (arr[i] == null) {
temp = i;
break;
}
}
int i,j;
Integer swap;
for(i = 0; i<temp; i++){
for (j = 0; j<temp-1-i;j++){
if (arr[j] > arr[j+1]){
swap = arr[j];
arr[j] = arr[j+1];
arr[j+1] = swap;
}
}
}
System.out.print("\n冒泡排序:");
iterator();
}
import java.util.Arrays;
public class Demo07 {
public static void main(String[] args) {
// 定义一个a数组
int[] a = new int[] { 3, 4, 5, 6 };
// 定义一个a2数组
int[] a2 = new int[] { 3, 4, 5, 6 };
// a数组和a2数组的长度相等,毎个元素依次相等,将输出true
System.out.println("a数组和a2数组是否相等:" + Arrays.equals(a, a2));
// 通过复制a数组,生成一个新的b数组
int[] b = Arrays.copyOf(a, 6);
System.out.println("a数组和b数组是否相等:" + Arrays.equals(a, b));
// 输出b数组的元素,将输出[3, 4, 5, 6, 0, 0]
System.out.println("b 数组的元素为:" + Arrays.toString(b));
// 将b数组的第3个元素(包括)到第5个元素(不包括)賦值为1
Arrays.fill(b, 2, 4, 1);
// 输出b数组的元素,将输出[3, 4, 1, 1, 0, 0]
System.out.println("b 数组的元素为:" + Arrays.toString(b));
// 对b数组进行排序
Arrays.sort(b);
// 输出b数组的元素.将输出[0,0,1,1,3,4]
System.out.println("b数组的元素为:" + Arrays.toString(b));
}
}
在 Java 中二维数组被看作数组的数组,即二维数组为一个特殊的一维数组,其每个元素又是一个一维数组。
创建二维数组
int[][] age;
初始化二维数组
age = new int[][]{
{1,2,3},{2,1,5}
};
对象是类的一个实例,有状态和行为。
类是一个模板,它描述一类对象的行为和状态。
成员变量就是定义在类里方法外的变量,这些变量没有使用static修饰。
成员变量又分为:实例变量和类变量。
成员变量的存储:没有实例化的成员变量放在栈中;实例化后的对象放在堆中,栈中放的是指向堆中对象的引用地址。
成员变量在对象被创建时而存在,当对象被GC回收时消失,生存周期适中。
成员变量作用在整个类中(静态方法除外),不能在定义的同时进行初始化,只能通过对象访问。
对象的构造方法可以自定义
1.构造方法使用public修饰
2.构造方法没有返回值类型(连void都没有)
3.构造方法的名字必须与当前类名相同
4.构造方法的内部有一个this指针,指向当前对象
5.如果一个类没有手动指定构造方法,则编译器会提供一个默认的构造方法
如果手动指定了构造方法,那么编译器将不在会提供默认的构造方法
无参构造方法存在的意义
在堆区构造一个对象,对象中的元素存储的数据还未知,后续的代码在获得数据以后,
可以通过指针操作对象,读写数据。
带参构造方法存在的意义
在堆区构造一个对象的时候,已经很明确知道对象中存在的数据是什么内容,
就可以使用带参构造方法,更方便
成员方法
成员方法(不加static,因为加了static就变成了静态函数)
用哪一个指针调用成员方法入栈执行那么栈帧中的this就指向哪个对象.
this.属性名
可用于任何实例方法内指向当前对象,也可指向对其调用当前方法的对象,或者在需要当前类型对象引用时使用。
假设有一个学生类如下:
public class Student {
int number;
String name;
int age;
char sex;
public Student(){
}
上述的成员变量在类外部无法对它们的值进行进行设置,为了解决这个问题,可以为这个Student类添加一个构造方法,如何在构造方法中传递参数进行修改,代码如下:
public Student(int number,String name,int age,char sex) {
this.number = number;
this.name = name;
this.age = age;
this.sex = sex;
}
this.方法名
this( )访问构造方法
new关键字申请内存空间,并且擦除的一干二净–>用0覆盖,具体如下图:
byte[] arr1 = new byte[10];
//arr1[1] = 128; //128超出了byte的范围
short[] arr2 = new short[10];
//在堆区中开辟内存空间,在栈区的局部变量表中创建arr3,把整个地址赋值给arr3
int[] arr3 = new int[10];
long[] arr4 = new long[10];
float[] arr5 = new float[10];
double[] arr6 = new double[10];
//验证char类型数组中的元素默认是字符集中的0号字符 '\u0000' ,是空字符
char[] arr7 = new char[10];
System.out.println(arr7[8] == 0);
boolean[] arr8 = new boolean[10];
String[] arr9 = new String[10];
//'' 空字符,"" 空字符串,null 空地址