数组是相同类型数据的有序集合
可以通过下标来访问,下标从0开始
首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法:
dataType[] arrayRefVar; // 首选的方法
dataType arrayRefVar[]; // 效果相同,但不是首选方法
Java语言使用new操作符来创建数组,语法如下:
arrayRefVar = new dataType[arraySize];
上面的语法语句做了两件事:
当然也可以使用一行代码完成声明和创建:
int[] numbers = new int[100];
可以通过numbers.length获取长度
有三种初始化
静态初始化:
int[] numbers = {1,2,3}; Person[] people = {new Person(),new Person()};
动态初始化:包含默认初始化
int[] numbers = new int[10]; b[0] = 1;
默认初始化:数组是引用类型,其中的元素相当于类的实例变量,因此数组一经分配空间,其中的元素就按照实例变量同样的方式被隐式初始化。
Java内存分为:
声明数组时,数组并不存在,只是在栈中压入一个变量
创建数组时,数组才会存在,在堆中真正地开辟出空间
访问下标超出数组大小会产生下标越界异常。
数组的元素还是数组
int[][] nums = new int[2][5]; int[][] numbers = {{1,2},{3,4},{5,6}};
数组的工具类java.util.Arrays
Arrays类中的方法都是static修饰的静态方法,可以直接使用类名调用
有以下常用功能
public static void sort(int[] array){ for(int i=0;i<array.length-1;i++){ boolean flag = false;//优化,跳过没有意义的比较轮次 //减i是因为进行i次比较后,产生了i个最大或最小的数不需要进行下次比较 for(int j=0;j<array.length-1-i;j++){ if(array[j+1]<array[j]) swap(array[j+1],array[j]); } if(flag == flase) break; } }
数组中大部分为0,或其他相同元素时,采用的一种压缩存储方式。
即只记录数组行列等基本信息,以及有效信息
面向过程
面向对象
以类的方式组织代码,以对象的方式封装数据
回顾:如何定义方法
静态方法:可以通过类名调用
非静态方法:需要实例化对象,借用对象调用
形参实参
值传递引用传递
this关键字:用来表示当前对象本身,或当前类的一个实例,通过 this 可以调用本对象的所有方法和属性。
使用new创建对象,创建时会
构造方法
一旦定义了有参构造,无参构造就必须显式定义
new本质是在调用构造器
内存分析
高内聚,低耦合
封装:数据的隐藏,将数据封装起来,只暴露给外界接口
属性:private
方法:getter/setter
封装的优点:
继承是类于类之间的关系,除此之外类与类之间的关系还有依赖,组合,聚合。继承:is a关系
Java只有单继承
控制访问与继承的规则:
Object类
在Java中,所有的类都继承了Object类
super关键字:表示当前类的父类
一般在写了带参数构造器后,都需要显式写出无参构造器
方法重写
重写是方法的重写与属性无关
静态方法:方法调用只和定义时的类有关,其实是通过类名在调用
非静态方法:重写,用实例化对象调用
父类
public class A { public static void test_static(){ System.out.println("A=>test_static"); } public void test(){ System.out.println("A=>test"); } }
子类
public class B extends A{ public static void test_static(){ System.out.println("B=>test_static"); } @Override public void test(){ System.out.println("B=>test"); } }
测试
public class test { public static void main(String[] args) { B b = new B(); A a= new B(); b.test_static(); a.test_static(); a.test(); b.test(); } }
输出
B=>test_static A=>test_static B=>test B=>test
总结
不能重写的方法
不能继承的类
动态编译:类型在执行时才能确定
同一方法可以根据发送对象的不同而采用多种不同的行为方式
一个对象的实际类型是确定的
但可以指向的引用类型就不一定了,父类引用可以指向子类的对象
父类
public class Person { public void run(){ System.out.println("run"); } }
子类
public class Student extends Person{ public void eat(){ System.out.println("eat"); } @Override public void run() { System.out.println("sonRun");; } }
测试
public class Test { public static void main(String[] args) { Student s1 = new Student(); Person s2 = new Student(); s1.run();//两个类型都有run方法且子类重写,执行子类的 s2.run(); s1.eat();//eat方法是子类独有的,父类无法调用 //s2.eat();//报错 } }
输出
sonRun sonRun eat
总结:
多态是方法的多态,属性没有多态
多态存在条件:
多态的实现可以有以下几种:
判断一个类型是不是某种类型
A instanceof B
看A和B有没有继承关系,
同级别类是无法通过编译的
引用类型转换
同样的高转低要强制转换
低转高是直接实现可以的
如果子类转为父类就可能会丢失一些子类自己本来的方法
子类转父类 向上转型
父类转子类 向下转型 强制转换
static变量
static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本【存放在方法区】,它当且仅当在类初次加载时会被初始化【加final和不加final的static变量初始化的位置不一样】。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
static方法
static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
static静态代码块
static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次【根据class加载原理 每个类加载一次 使用双亲委托加载】。
初始化的顺序 静态代码块 > 构造代码块 > 构造函数
测试
public class Test { { System.out.println("匿名代码块"); } static{ System.out.println("静态代码块"); } public Test(){ System.out.println("构造方法"); } public static void main(String[] args) { Test test = new Test(); System.out.println("========="); Test test2 = new Test(); } }
执行
静态代码块 匿名代码块 构造方法 ========= 匿名代码块 构造方法
static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次,之后会按匿名代码块,构造方法的顺序执行
很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。
静态内部类
pass
静态导包
import static java.lang.Math.random;//下面使用时可以直接调用random()
abstract修饰符可以修饰方法也可以修饰类,abstract修饰方法就是抽象方法,abstract修饰类就是抽象类。
抽象类中可以没有抽象方法,但是一旦定义的抽象方法就必须声明为抽象类。抽象类也可以写普通方法。
抽象类:不能实例化,不能new,它就是用来让别人继承的
抽象方法:只有方法的声明,没有实现,子类需要实现。
子类继承抽象类就需要实现抽象方法,否则它也应当声明为抽象类
但是抽象类本质还是一个类,别人需要用extends继承,但是Java只有单继承
这是需要引入接口,接口可以实现多继承
思考:抽象类也存在构造器
接口:只有规范。可以实现约束和实现分离--->面向接口编程
接口就是规范,定义的是一组规则。体现的是现实世界中“如果你是...则必须能...”的思想
接口的本质是契约,像法律,制定好了大家都要遵守
面向对象的精髓,是对对象的抽象,最能体现这一点的就是接口。
设计模式其实就是在研究:如何合理地去抽象
接口中定义方法都是抽象的,而且默认是public abstract,可以不写
接口中定义的属性都是常量,默认public static final,一般没人在接口里定义属性
使用接口时要注意锻炼自己的抽象思维能力
总结
内部类就是在类的内部再定义一个类
一个java类可以有多个class,但只能有一个public class
成员内部类
静态内部类
局部内部类
匿名内部类
程序运行时出现的不期而至的情况,文件找不到,网络链接失败等
要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
所有的异常类是从 java.lang.Exception 类继承的子类。
Exception 类是 Throwable 类的子类。除了Exception类外,Throwable还有一个子类Error 。
Java 程序通常不捕获错误。错误一般发生在严重故障时,它们在Java程序处理的范畴之外。
Error 用来指示运行时环境发生的错误。
例如,JVM 内存溢出。一般地,程序不会从错误中恢复。
异常类有两个主要的子类:IOException 类和 RuntimeException 类。
Throwable Exception Error IOException RuntimeExceptionError类对象由Java虚拟机生成并抛出,大多数错误与代码编写者执行的操作无关。
Error是灾难性的致命的错误,是程序无法控制和处理的
Exception通常是可以被程序处理的。我们应当尽量避免一些异常的产生。
抛出异常
捕获异常
五个关键字
try,catch,finally,throw,throws
主动抛出异常
一般在方法中使用。
if(b == 0){ throw new ArithmeticException(); }
在方法上抛出异常throws
public void method(int a,int b) throws IOException{ }
在 Java 中你可以自定义异常。编写自己的异常类时需要记住下面的几点。
可以像下面这样定义自己的异常类:
class MyException extends Exception{ }
实例
public class MyException extends Exception { private int number; public MyException(int number) { this.number = number; } @Override public String toString(){ return "MyException: "+number; } } ##转载,仅供自己学习##