目录
1、封装:
用于保护或者防止代码被我们无意中破坏
保护成员属性,不让类以外的程序直接访问和修改 (private,public,getter,setter)
封装原则:
隐藏对象的属性和实现细节,仅公开对外方法,并且控制访问级别
2、this:
在Java基础中,this关键字是一个最重要的概念。使用this关键字可以完成以下的操作:
· 调用类中的属性
· 调用类中的方法或构造方法
· 表示当前对象
在一个构造方法A中,调用另一个构造方法B时,必须编写在A的第一行:
Class Person{
private String name;
private int age;
Person(){
调用另一个构造方法时,必须编写在的第一行:
//设置默认的姓名和年龄
this.Person("默认姓名",1);
}
Person(String name,int age){
this.name = name;
this.age = age;
}
}
3、static:
静态成员 在类加载时加载并初始化。
无论一个类存在多少个对象 , 静态的属性, 永远在内存中只有一份( 可以理解为所有对象公用 )
在类中定义一个static变量,无论new多少个类,所有的类都是公用该静态变量
在访问时: 静态不能访问非静态 , 非静态可以访问静态 !
4、代码块:
构造方法 与 构造代码块 以及 静态代码块的执行顺序:
静态代码块 --> 构造代码块 --> 构造方法
static{} {} public Person(){}
构造方法可能重载,会有多个,无论执行哪一个构造方法,都会执行构造方法块,所以如果所有的构造方法,都要执行某些命令,就可以写在构造代码块里
类加载参考 https://blog.csdn.net/ns_code/article/details/17881581
5、继承
new一个子类前,会先找到该类的父类,先在内存中,把父类创建,才会创建子类
子类构造方法中,调用super构造方法,必须放在子类的第一行
6、重写
声明为static和private的方法不能被重写,但是能够被再次声明
重写和重载的区别
重写(Overriding) | 重载(Overloading) | |
范围 | 父子类、接口与实现类 | 本类 |
方法名称 | 一致 | 一致 |
参数列表 | 一定不能修改 | 必须修改 |
返回类型 | 一定不能修改 | 可以修改 |
异常 | 可以减少或删除,但不能扩展 | 可以修改 |
7、final
final修饰局部变量,如果没有赋默认值,则可以且只能赋值一次
final修饰全局变量,必须在声明是赋值
final修饰类,不能被继承
final修饰方法,不能被子类继承
8、abstract
抽象类可以有非抽象的方法
抽象类不能直接new对象,只能new他的非抽象子类
抽象类不能被final声明,因为抽象类必须被继承
抽象类可以有构造函数,而且子类对象实例化的时候的流程与普通类的继承是一样的,都是要先调用父类中的
构造方法(默认是无参的),之后再调用子类自己的构造方法。
new抽象类的子类时,JVM也会创建抽象类到内存中,也会执行构造方法
抽象类必须用public或者protected修饰,不写的话,默认也是public,因为抽象类必须要被继承
子类继承抽象类,必须实现抽象类的抽象方法。如果子类不能实现所有抽象方法,那么子类也必须定义为抽象类
9、接口
优点:
1、 降低程序的耦合性
2、 易于程序的扩展
3、 有利于程序的维护
因为接口本身都是由全局常量和抽象方法组成 , 所以接口中的成员定义可以简写:
1、全局常量编写时, 可以省略public static final 关键字,例如:
public static final String INFO = "内容" ;
简写后:
String INFO = "内容" ;
2、抽象方法编写时, 可以省略 public abstract 关键字, 例如:
public abstract void print() ;
简写后:
void print() ;
接口因为都是抽象部分, 不存在具体的实现, 所以允许多继承,例如:
interface C extends A,B{
}
抽象类可以实现接口,但是可以不实现接口中的方法
抽象类和接口的区别
1、抽象类要被子类继承,接口要被类实现。
2、接口只能声明抽象方法,抽象类中可以声明抽象方法,也可以写非抽象方法。
3、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
4、抽象类使用继承来使用, 无法多继承。 接口使用实现来使用, 可以多实现
5、抽象类中可以包含static方法 ,但是接口中不允许(静态方法不能被子类重写,因此接口中不能声明
静态方法)
6、接口不能有构造方法,但是抽象类可以有
10、多态
多态:就是对象的多种表现形式
方法的重载 和 重写 也是多态的一种, 不过是方法的多态(相同方法名的多种形态)。
重载: 一个类中方法的多态性体现
重写: 子父类中方法的多态性体现。
类似于基本数据类型的转换:
· 向上转型:将子类实例变为父类实例
|- 格式:父类 父类对象 = 子类实例 ;
· 向下转型:将父类实例变为子类实例
|- 格式:子类 子类对象 = (子类)父类实例 ;
11、内部类
成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默
认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
外部使用成员内部类
Outter outter = new Outter();
Outter.Inner inner = outter.new Inner();
匿名内部类的过程中,我们需要注意如下几点:
1、使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能
继承一个类或者实现一个接口。
2、匿名内部类中是不能定义构造函数的。
3、匿名内部类中不能存在任何的静态成员变量和静态方法。
4、匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
5、匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
6、只能访问final型的局部变量
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。
静态内部类是不需要依赖于外部类对象的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非
static成员变量或者方法.
12、包装类
八种包装类也是分为两种大的类型的:
· Number:Integer、Short、Long、Double、Float、Byte都是Number的子类表示是一个
数字。
· Object:Character、Boolean都是Object的直接子类。
13、可变参数
语法:
返回值类型 方法名称(数据类型…参数名称){
//参数在方法内部 , 以数组的形式来接收
}
注意:
可变参数只能出现在参数列表的最后。
14、异常
受检异常:没执行的时候,编译器就会提示可能会报错的异常
非受检异常 (RuntimeException的子类):执行程序的时候,才会报的异常
try_catch异常处理流程
1、 一旦产生异常,则系统会自动产生一个异常类的实例化对象。
2、 那么,此时如果异常发生在try语句,则会自动找到匹配的catch语句执行,如果没有在try语句中,则会将异
常抛出.
3、 所有的catch根据方法的参数匹配异常类的实例化对象,如果匹配成功,则表示由此catch进行处理。
15、finally
在进行异常的处理之后,在异常的处理格式中还有一个finally语句,那么此语句将作为异常的统一出口,不管是否产生
了异常,最终都要执行此段代码,除非在finally执行之前,包括在执行catch的时候,系统退出了(执行退出命令,程序被关闭,断电,关机等等),这样就不会执行finally中的内容
如果想捕获异常抛出时抛出,又要进行finally
可以这么写。这样就不用写catch,有异常直接抛,并且还能执行finally,
try {
a=123;
}finally {
//要进行的操作
}
如果在try中return,也会在return前,执行finally。
但是在finally中进行赋值操作,会影响结果
1、引用数据类型:在15行return的时候,会把栈内存中p1的存的值(内存地址0x123)复制一份出来,变成p1_copy=0x123,然后p1_copy准备传给main里的p,这时候执行了p1.age=100的操作,因为p1.age存放在堆内存,就会把堆内存中,0x123中,p1.age的值,改为100。这时候执行p1=p2,只是把复制前的,在栈内存中的p1的指针,改为0x124,但是实际上传回去的,是复制出来的p1_copy的内存,0x123,而在finally中进行的操作,就是对0x123的值进行修改,所以,输出p的时候,age=100
public class Main {
public static void main(String[] args) {
Person p = haha();
System.out.println(p.age);//输出的结果为100
}
private static Person haha() {
Person p1 = new Person();
Person p2 = new Person();
try {
p1.age = 10;
p2.age = 20;
return p1;
} catch (Exception e) {
return null;
}finally {
p1.age = 100;
p1 = p2;
p2.age = 300;
}
}
}
class Person{
int age;
}
2、非引用数据类型:在执行13行return的时候,会先把栈内存中,a1存的值10。复制一份出来为a1_copy,然后准备把a1_copy=10传回去,准备阶段中,a1=100,a1=a2,都是对复制前的a1进行操作,不影响实际传回去的a1_copy的值。因为对非引用类型进行修改,都是在栈内存中进行修改。所以把a1=100,不会对a1_copy进行操作,所以结果输出的也是10。
public class Main {
public static void main(String[] args) {
int a = haha();
System.out.println(a);
}
private static int haha() {
int a1 = 10;
int a2 = 200;
try {
return a1;
} catch (Exception e) {
return 0;
}finally {
a1 = 100;
a1 = a2;
}
}
}