注:基础语法不做过多学习,从数组开始。
数组
1.数组的创建
int[] x; //静态创建1
x=new int[]{1,1,1};
int[] y={1,1,1}; //静态创建2
int[] x1=new int[3]; //动态创建
x1[0]=1;
2.数组排序
2.1.选择排序
public void selection(int[] x){
int[] x=new int[]{5,4,3,7,6,10,8,9,2,1};
for (int i = 0; i < x.length; i++) {
int minIndex=i; //默认最小值索引为第一个元素
for (int j=i+1;j<x.length;j++){
if (x[j]<x[minIndex]){ //交换元素值
int temp;
temp=x[j];
x[j]=x[minIndex];
x[minIndex]=temp;
}
}
}
System.out.println(Arrays.toString(x)); //打印元素
}
2.2.冒泡排序
public static void Bubble(int[] x){
for (int i = 0; i < x.length-1; i++) { //循环次数为数组长度-1,因为最后一次不用作比较(只有一个元素)
for (int j=0;j<x.length-i-1;j++){ //每次都是从第一个元素开始与后面元素开始比较
if (x[j]>x[j+1]){ //交换
int temp;
temp=x[j];
x[j]=x[j+1];
x[j+1]=temp;
}
}
}
System.out.println(Arrays.toString(x));
}
2.3*.快速排序*
Arrays.sort(x);
3.fill方法
int[] y=new int[5];
Arrays.fill(y,3);
int[] z=new int[5];
Arrays.fill(z,2,4,23);
4.copyOf,copyOfRange和System.arraycopy方法
int[] x={1,2,3,4,5,6};
int[] y=Arrays.copyOf(x,10); //如果长度超过原数组长度,则用0补
int[] z=Arrays.copyOfRange(x,1,3); //复制范围是[1,3)
int[] a=new int[5];
System.arraycopy(x,1,a,2,2);//参数1 :源数组 参数2:从源数组哪个下标开始复制
// 参数3:复制到的目标数组 //参数4: 从目标数组的哪个下标位置开始放入 参数5:复制源数组多长
5.数组的equals方法和compare方法
int[] x={1,2,3,4,5,6};
int[] y={1,2,3,4,5,6};
boolean b = Arrays.equals(x, y);//两个数组相同,返回true,否则false
int i = Arrays.compare(x, y);//x>y,返回1,相同0,x<y返回-1
6.二维数组
int[][] x={{1,2},{3,4},{5,6,7},{8},{9,10}};//静态创建二维数组1
int[][] y; //静态创建二维数组2
y=new int[][]{{1,2},{3,4},{5,6,7},{8},{9,10}};
int[][] z=new int[3][]; //动态创建二维数组,第二维还没有初始化引用时会出现异常
//z[0]={1,2,3};
int[] a=new int[]{1,2,3};
int[] a1=new int[]{2,3};
int[] a2=new int[]{1};
z[0]=a;
z[1]=a1;
z[2]=a2;
类
1.成员变量与局部变量的区别
java类的成员变量,都有默认值
整数:0
浮点数:0.0
boolean:false
字符:‘\u0000’
引用类型:null
java类的成员变量,在下面所有的方法中,都可以访问到
局部变量,没有默认值
方法体中声明的变量
方法参数中的变量
代码块中的变量
成员变量有默认值,局部变量没有默认值,产生的原因?
JVM进行类加载和字节码执行,这两个阶段时依次执行
JVM(Java虚拟机)通过ClassLoader类加载器进行类加载,过程涉及到"加载"、“准备”、"解析"和初始
化,类的成员变量初始化,是在JVM类加载的阶段完成。
成员变量:静态(static)成员变量、非静态成员变量(初始化阶段赋值,根据代码中的赋值情况,如果没有
赋值,则使用默认值,有赋值,则使用代码中的赋值。当对象实例化后,成员变量会随着对象分配到
java堆内存中)。
局部变量:存储在栈内存中
2.对象创建的原理
程序计数器、Java栈、堆、本地方法栈、方法区
当我们创建一个对象时,同时操作了栈和堆
在栈内存中保存对象的引用
对象的属性保存中堆内存中
操作对象都是通过引用完成,一旦引用出栈,没有被引用的对象就变成了垃圾,应该被回收
编写类文件的时候,类文件存储在硬盘上,还没有被加载到内存中。在主方法中,创建了这个类的对
象,才会被加载到内存中,进行处理。
3.构造器
-
也称作构造器,严格来讲,构造方法不是方法
-
构造方法要求和类名相同,没有返回值类型,也没有void,可以有return,表示方法的结束,不能返
回值。
-
构造方法主要作用是完成对象的初始化工作。
-
每个java类,都至少有一个构造方法,如果不写构造方法,编译器会自动提供一个构造方法,没有
任何参数和语句的,默认的空构造方法。如果一旦写了构造方法,编译器不会再提供默认的构造方
法。
-
一个类可以定义多个构造方法(构造方法的重载)
-
一般情况,都会写一个无参的构造方法,这是一个好的编程习惯
-
构造方法的调用:
如果是在其他类中,通过new 的方式来调用构造方法
如果是在自己的类中,可以在构造方法之间进行互相调用。使用this([参数])。必须写在构造方
法中的第一行
8.快捷生成 alt+insert
4.static
4.1.概述
类成员变量或静态成员变量:使用static修饰的,作用范围在整个类的所有对象上。所有对象共享这个变
量,在内存中只有一个副本。访问通过 类名.变量名 访问。在类加载时被初始化,存储在堆里。
实例成员变量:没有static修饰,作用范围在某个实例对象上。在创建对象时被初始化,存在多个副本。
各个对象不互相影响。通过 实例对象名.变量名 访问
类方法或静态方法:使用static修饰,不能直接使用实例变量,只能直接使用静态变量。只能直接调用静
态方法,不能直接调用实例方法。通过 类名.方法名() 访问
不允许使用this关键字
实例方法:没有static修饰,既可以使用静态变量,又可以使用实例变量。既可以直接访问实例方法,又
可以直接访问静态方法。 通过 实例对象名.方法名() 访问
静态代码块>构造代码块>构造方法
静态代码块:类加载的时候执行,并且只执行一次,优先于各种代码块和构造方法,最开始执行的。
构造代码块:在创建对象时被调用,每创建一次对象,都会执行一次构造代码块。 执行顺序,优先于构
造方法执行。一个类如果有多个构造方法时,每通过构造方法,创建一个对象,代码块都会被执行一
次。但是对于构造方法来讲,只执行某一个构造方法(根据参数执行)。
4.2.案例:统计类创建了多少个对象
public class Test2 {
public static void main(String[] args) {
K k1=new K(1);
K k2=new K("abc");
K k3=new K(1,"abc");
K k4=new K();
System.out.println(K.count);
}
}
class K{
private int x;
private String y;
public static int count;
{
count++; //构造代码块,每创建一个对象调用一次
}
public K() {
}
public K(int x, String y) {
this.x = x;
this.y = y;
}
public K(String y) {
this.y = y;
}
public K(int x) {
this.x = x;
}
}
4.3.单例模式
设计模式:在某些项目环境下,针对某些问题,提供的一种通用的解决方案。
Gang of Four(GOF):23种软件设计模式
单例模式:保证一个类只能创建一个实例对象,自行实例化,并向整个系统提供这个对象。
实现:
构造方法私有
提供一个当前类的私有静态成员变量
提供一个公有的静态方法,返回成员变量
class Single{ //单例模式
private static final Single singleInstance=new Single();
Single(){}
public static Single getInstance(){
return singleInstance;
}
}
class Single2{ //懒汉式单例模式
private static Single singleInstance;
Single2(){}
public static Single getInstance(){
if (singleInstance==null) {
singleInstance = new Single();
return singleInstance;
}
return singleInstance;
}
}
5.访问修饰符
private | default | protected | public | |
---|---|---|---|---|
同类 | T | T | T | T |
同包 | F | T | T | T |
子类 | F | F | T | T |
通用性 | F | F | F | T |
类的访问修饰符
public :所有类都可以访问
继承
1.子类实例化过程
-
父类的构造方法,不能被子继承
-
在子类的构造方法中,调用了父类的构造方法
-
如果父类有无参的构造方法,子类super()可以省略
-
如果父类中没有无参的构造方法,子类super(参数)不可以省略
-
如果使用super()显式地调用父类的构造方法,要求必须写在子类构造方法中的第一行
-
子类的构造方法中,不能同时出现super()和this()
在子类创建对象时,是否也创建了父类的对象。答:不会创建父类对象。只是创建了父类空间,并进行
了初始化操作。
2.属性的隐藏
在父类中定义一个属性,在子类中定义了一个同名的属性,在子类中访问,会隐藏父类的属性
在子类中,有两个同名属性,一个是继承自父类的,使用super.属性名访问,一个是子类自己的,使用
this.属性名访问
在方法中,如果访问到属性,继承自父类的方法,使用的是父类的属性,子类自己的方法,使用的是子
类属性。
如果父类中有一个静态变量,则被所有子类所共享,其中一个子类修改了值,其他子类访问也是修改后
的值。如果子类自己写了一个同名的静态变量,则子类中访问的是自己的变量,不再是父类变量
3.方法覆盖
java的类只支持单继承,一个类只能有一个直接父类
也叫作方法重写,子类中对父类(祖先类)存在的同名方法,进行改造,去覆盖父类同名方法的机制。
方法重写的要求:
1、方法名必须相同
2、参数列表必须相同
3、访问修饰符 大于等于父类方法的访问修饰符
4、父类方法不能是私有的
5、返回值类型 小于等于父类方法的返回值类型
6、异常处理:
运行时异常:
子类方法,可以自行决定,抛出任何类型的运行时异常,父类的方法不受影响
检查型异常
父类抛出了检查型异常,子类可以不抛出任何异常或者子类可以抛出相同类型异常,或者子类可以抛
出比父类方法异常小的异常类。不能抛出比父类方法异常大的异常,也不能抛出和父类方法不同的其他
类型检查型异常
使用方法重写的场景:子类和父类的方法要完成相同功能,但采用不同的算法或公式。
4.final
final不可以和abstract放在一起对方法和类进行修饰
final定义常量:
修饰引用类型: 无法更改引用所指向的对象地址。引用的对象属性可以修改。
修饰基本数据类型:值不能被修改
编译期常量、非编译期常量
不是所有的final修饰的字段都是编译期常量,非编译期常量,在被初始化之后无法修改
static final:
一个既是static,又是final的字段,只占据一段不能改变的存储空间。
final定义终结类:
当一个类定义为final 时,就表明不能继承这个类,表示不能产生子类。
final类里面的所有方法,都是隐式的final,不会产生子类,也不会覆盖方法,所以不需要在final类中
为方法加final关键字。
final定义终结方法:
不能被子类重写。所有private方法都是隐式地final方法,在private方法中,不需要使用final关键
字修饰。
final方法可以被重载
final的初始化:
类的普通成员变量,在定义时,可以直接初始化,也可以先不做初始化,在构造方法或构造代码块
中,进行初始化
类的静态成员变量,在定义时,可以直接初始化,也可以先不做初始化,在静态代码块中,进行初
始化
class Test {
private final int c;{
c=1;
}
private static final int x;
static {
x=2;
}
5.多态
5.1.向上转型(上溯造型)
父类的引用指向子类的对象(将子类对象赋值给父类对象)
父类类型 对象名=new 子类类型();
编译时,看左边,运行时,看右边。
只能调用到父类中声明过的方法,不能调用子类中的特殊方法
方法的运行,看子类的结果
属性的调用,看左边
将子类声明成父类类型,得到的对象编译时认为是父类的,运行时认为是子类的,属性是父类的,方法
是子类的。
5.2.向下转型(下溯造型)
子类的引用指向父类的引用
语法: 子类类型 对象名=(子类类型)父类引用;
只能强制转换父类的引用,不能强制转换父类的对象,如果强制转换,编译可以通过,运行时报错误。
转换的前提是父类的引用必须是经过向上转型的对象
可以调用子类中声明的所有方法
5.3.多态
具有多种表现形态,三个必要条件
-
要有继承
-
要有重写
-
父类引用指向子类对象
优点
简化代码
面向抽象编程,不面向具体编程。(依赖倒转原则)
易于扩展 增强代码可读性
5.4.静态方法能否重写
子类可以写一个和父类相同的静态方法,当使用多态机制,将子类声明成父类类型时,调用的静态方
法,还是父类的静态方法,不能实现方法的覆盖。
必须要重写的方法:abstract修饰的抽象方法
不能重写的方法:构造方法、private、final、static
接口
1.JDK8新增方法
default方法(JDK8)
static方法(JDK8)
private方法(JDK9)
public interface Inter1 {
default void test(){ //默认方法,实现这个接口时,默认继承了这个方法,可以重写也可以不重写
System.out.println("11111111");
test2();
}
static void test1(){ //静态方法,接口名调用
System.out.println("2222222222");
}
private void test2(){ //接口中默认public,private方法用于接口中的其他方法调用,且只能接口内方法调用
System.out.println("33333333333");
}
}
2.内部类
2.1.成员内部类
成员内部类**(普通内部类)**:可以直接访问外部类的变量和方法(包括私有和静态修饰的)。不能
使用static声明变量和方法的。编译后生成的class文件命名为 “外部类名$内部类名”。不能直
接new一个内部类对象,必须使用外部类对象来创建内部类对象
如果外部类和内部类具有相同名称的成员变量或方法,内部类可以直接访问内部类的成员变量
和方法的,如果内部类访问外部类的成员变量或方法时,需要this关键字
public class Test {
public static void main(String[] args) {
Outer outer=new Outer();
Outer.Inner inner=outer.new Inner();
outer.test(); //外部类函数
inner.test(); //内部类函数
System.out.println(outer.getX()); //外部类的x
System.out.println(inner.getX()); //内部类的x
System.out.println(inner.getY());
}
}
class Outer{
public int getX() {
return x;
}
private int x=10;
public void test(){
System.out.println("Outer----");
}
class Inner{
public int getY() {
return y;
}
public int getX() {
return x;
}
private int y=9;
private int x=7;
public void test(){
System.out.println("Inner----"+Outer.this.x);//外部类的x
}
}
}
2.2.静态内部类
静态内部类:使用static修饰的内部类,不能直接访问外部类的非静态成员变量和方法。如果要
访问外部类的实例变量和方法,需要创建外部类的实例对象。可以创建静态变量和方法。静态
内部类创建对象时,不需要创建外部类的对象,直接可以创建内部类的对象
public class Test1 {
public static void main(String[] args) {
Outer1.Inner1 inner1=new Outer1.Inner1(); //可以直接创建内部类对象
System.out.println(inner1.test());
System.out.println(inner1.run());
}
}
class Outer1{
private static int x=10;
private int y=9;
public void test(){
}
public static void test1(){
}
static class Inner1{
private int x=1;
private static int z=5;
public int test(){
Outer1.test1();
return Outer1.x; //不能访问外部类的非static成员变量y和函数test()
}
public int run(){
Outer1 outer1=new Outer1(); //需要创建外部类的对象才能访问问问罢了的非static方法和变量
outer1.test();
return outer1.y;
}
}
}
2.3.局部内部类
局部内部类:定义在外部类的方法或代码块中。可以直接访问外部类的所有成员变量和方法(包
括私有的、静态的),不能使用访问修饰符(地位相当于局部变量),可以使用final修饰,防止其
他类去继承。作用范围就在当前的方法或代码块中。
局部内部类访问方法中的变量,jdk1.8之前,必须要求变量是使用final修饰,jdk1.8之后,加入了语法
糖,默认有final修饰,所以在局部内部类方法中,可以访问,但不能修改。
如果局部变量发生了改变,对于匿名内部来讲,是不知道的,所以为了保证数据运行的一致性,使用
final来修饰。
class OuterLocal{ //正确代码
private int x=10;
private static void test2(){ }
public void testn(){ }
public int test(){
int y=10;
int finalY = y;
class InnerLocal{
public void test1(){
System.out.println(finalY);
}
}
InnerLocal local=new InnerLocal();
local.test1();
return ++y;
}
}
2.4.匿名内部类
匿名内部类:没有名字的一种嵌套类。在实际开发过程中,一个接口/父类的方法在程序员只会
执行一次,如果为了使用它,要创建它的实现类或子类去进行重写。此时,我们可以使用匿名
内部类的方法,减少代码冗余。
语法: new 接口/父类()