JAVA面向对象
package enjory; public class Test { public static Test t1 = new Test(); public static Test t2 = new Test(); { System.out.println("非静态块"); } static { System.out.println("静态块"); } public Test() { // TODO Auto-generated constructor stub System.out.println("构造函数"); } public static void main(String[] args) { Test t = new Test(); } }
public class Testa { public static T t1 = new T(); public static void main(String[] args) { T a1 = new T(); T a2 = new T(); } } class T { { System.out.println("非静态初始化块"); } static { System.out.println("静态初始化块"); } public T() { System.out.println("无参的构造方法"); } }
public class TEST { public static void main(String[] args) throws Exception { System.out.println("main:" + Tdsa.class); } private static class Tdsa { static { System.out.println("Tdsa................"); } } }
一、类的修饰符与一些小知识:
1、类的简单知识
①当我们打印一个对象的引用时,实际上默认调用的就是这个对象的toString方法
②类的可见性
public:可以被任何地方的其他类引用
缺省:只能被本包内的其他类引用
③成员变量和局部变量
局部变量必须显示的初始化,没有默认初始化值
成员变量会有默认的初始化的值
④类的修饰符
final
abstract
2、抽象类(是基于重写的)
①抽象类不可被实例化
②有构造器
③有抽象方法的类一定是抽象类
④没有抽象方法的类也可以为抽象类
⑤若子类继承抽象类,并重写了所有的抽象方法,那么这个类可以定义为实体类或者抽象类
⑥若子类继承抽象类,没有重写所有的抽象方法,那么这个类必须定义为抽象类,因为他里面继承了抽象方法
⑦抽象类的静态属性和静态方法是可以直接调用的
3、接口
①没有构造器
②只能有常量和抽象方法
③接口里面的常量修饰符都必须是(public static final)但是是可以省略的
④接口里面的方法的修饰符都必须是(public abstract)但是是可以省略的
⑤接口本身的修饰符是public或者缺省
⑥若子类实现接口,并重写了所有的抽象方法,那么这个类可以定义为实体类或者抽象类
⑥若子类实现接口,没有重写所有的抽象方法,那么这个类必须定义为抽象类,因为他里面继承了抽象方法
⑥一个类可以实现多个接口
⑦接口之间的可以多继承的
二、类的五类成员
1、属性
(1)可见性和修饰符
①可见性
public:
protected:
private:
缺省:
②修饰符
static
final
(2)属性的初始化过程:
属性的默认初始化 --> (属性的显示初始化 --> 代码块的执行) --> 构造器的赋值 --> setter方法的赋值;注意中间两个用括号括起来的两个部分是没有顺序的,谁写在前面就先执行谁。
final修饰的静态属性不支持默认初始化,(支持显示初始化,静态代码块初始化)只能其中一个赋值
final修饰的普通属性不支持默认初始化,(支持显示初始化,代码块初始化,构造器初始化)只能其中一个赋值
2、方法
(1)可见性
public:
protected:
缺省:
private:
(2)修饰符
static
final
abstract
3、构造器
(1)修饰符
public
protected
缺省
private
(2)特性
①抽象类也是有构造器的,只有接口没有构造器
②如果一个类没有定义构造器,那么会有一个默认的无参的构造器;如果定义了构造器,那么就没有默认的无参的构造器了
③类的多个构造器之间构成重载
④构造器不能被继承和不能被重写,但是可以被调用
⑤构造器的首行必须是this(args),this(),super(args),super()结构之一;当构造器中不显示调用时,首行默认调用的是super()父类空参的构造器,当然父类必须有空参的构造起了。
⑥java new的任何一个对象都会调用到Object类的Object()方法
⑦ava编译器会默认的给类生成一个空参数构造函数,而这个构造函数的访问级别是和类访问级别相同的
4、代码块
(1)静态代码块
①随着类的加载而加载,只被加载一次
②静态代码块的执行早于非静态代码块的执行
③静态代码块可以调用静态属性或者静态方法
(2)非静态代码块
①每创建一次对象,就执行一次非静态代码块
②它的执行早于构造器
③但是它的执行不一定就在属性显示初始化的前面,和他们在代码里的顺序有关,谁在前面就先执行谁
④非静态代码块里面可以调用属性和方法
5、内部类(成员内部类,局部内部类,匿名内部类,静态内部类)
局部内部类或者匿名内部类只能访问定义为final的局部变量
(1)成员内部类
修饰符:public,protected,缺省,private,static,final,abstract
①静态的
②非静态的
public class Main{ public static void main(String[] args) { //静态内部类的创建 W.A a = new W.A(); a.show(); //非静态内部类的创建 W w = new W(); W.B b = w.new B(); b.show(); } } class W { String name = "wai"; static String id = "waiid"; static class A{ static String id = "neiid"; public void show() { System.out.println(id); System.out.println(W.id); } } class B{ String name = "nei"; public void show() { System.out.println(name); System.out.println(this.name); System.out.println(W.this.name); } } }
(2)局部内部类
public class Main{ public static void main(String[] args) { } } class J { //使用方式二 Comparable getComparable(){ class MyComparable implements Comparable{ @Override public int compareTo(Object o) { // TODO Auto-generated method stub return 0; } } return new MyComparable(); } //使用方式二 Comparable getComparable2(){ return new Comparable() { @Override public int compareTo(Object o) { // TODO Auto-generated method stub return 0; } }; } }
(3)内部类的可见性
三、面向对象的三个特征
1、封装性
属性私有化,增加getter和setter的方法
2、继承性
3、多态性
①属性是不存在多态性的,它是基于隐藏的;如果在③的情况下调用的是父类的属性。
②重载与重写的多态性的一种表现
③子类对象的多态性(把new出来的子类赋值给父类的引用)。
④继承和重写是多态性的前提
⑤接口与具体的实现类之间也是存在多态性的
四、关键字
1、this与super(是针对对象的,不针对类)
this和super不能出现在静态区域内
(1)this
this在java中就是指当前对象,在静态方法中不能出现
①修饰构造器(调用其它重载的构造器)这个结构必须在构造器的首行出现,这个结构只能在构造器里面出现
this()
this(args)
②修饰方法和属性
this.name
this.show()
(2)super
java中的super指的是继承的父类的对象,在静态方法中不能出现
①修饰属性和方法
super.name
super.show()
②修饰构造器(调用父类的构造器)这个结构必须在构造器的首行出现,这个结构只能在构造器里面出现
不写的话默认会调用super(),在这种情况下父类必须有无参构造器
super()
super(args)
2、static关键字
可以修饰:方法、属性、代码块、内部类
3、final关键字
final可以修饰类、属性和方法
①修饰的类不能被继承
②修饰的方法不能被重写
③final修饰的成员变量为常量
④final修饰局部变量和函数参数
⑤final修饰的引用变量,其变量内部的属性是可以改变的
4、abstract
可以修饰类和方法
10、注意的点
final和static可以同时修饰属性
final和static可以同时修饰方法
abstract只能和public或者protected或者缺省连用
abstract不能用来修饰属性、构造器、private、final、static
五、重写与重载
1、重载
前提条件:重载是针对方法来说的,
①在同一个类当中,(不在同一个类中的子父类之间的方法也可以重载)
②函数名字相同,
③但是参数个数不同或参数类型不同或参数顺序不同
④只有返回值不同是不可以的
2、重写(权限修饰符子类可以大于父类;返回值类型和异常子类可以小于父类)
重写是在继承的机制下才形成的,继承是前提
前提条件:重写是针对实例方法来说的
1、要求子父类有相同的“返回值类型 方法名(参数列表)”都相同(返回值类型父类比子类的范围大也是可以的)
2、子类方法的权限修饰符不能小于父类方法的权限修饰符
3、若父类方法抛异常,那么子类方法抛的异常不能大于父类方法抛的异常
4、子父类的方法必须同为static或者同为非static
方法不能交叉覆盖:子类实例方法不能覆盖父类的静态方法;子类的静态方法也不能覆盖父类的实例方法
注意:重写是对子类中可见的父类方法而言的,如果在父类中的方法在子类中不可见,那根本就不存在重写一说
上图中绿色小三角就代表这个方法重写了。
下图中说明:返回值类型父类比子类的范围大也是可以的
3、覆盖
覆盖就是重写
4、隐藏
隐藏是对于静态方法和成员变量(实例变量和静态变量)而言的,就是父类和子类有相同名字的属性,或者父类和子类有相同名字的静态方法时,
属性是可以交叉隐藏:子类的实例变量可以隐藏父类的静态变量;子类的静态变量可以隐藏父类的实例变量
5、原理
覆盖的原理是RTTI,也就是通过Class对象实现的,看的是=后面,运行时类型为引用变量所指向的对象的类型
隐藏就是根据单纯的静态类型实现的,看的是=前面,编译时类型是引用变量自身的类型
6、枚举
public class Main { public static void main(String[] args) throws Exception { // TODO Auto-generated method stub Rate[] rates = Rate.values(); for (Rate rate : rates) { System.out.print(rate); } System.out.println(); String str = "A"; Rate rate = Rate.valueOf(str); System.out.println(rate); // -------------------------------- Rate rate2 = Rate.getRateByNo(1); System.out.println(rate2); // --------------------------------- Rate.A.show(); Rate.B.show(); Rate.C.show(); } } interface Info { void show(); } enum Rate implements Info { A(0) { @Override public void show() { // TODO Auto-generated method stub System.out.println("Automtic"); } }, B(1) { @Override public void show() { // TODO Auto-generated method stub System.out.println("Bilibili"); } }, C(2) { @Override public void show() { // TODO Auto-generated method stub System.out.println("Customer"); } }; private Integer no; public Integer getNo() { return no; } public void setNo(Integer no) { this.no = no; } private Rate(Integer no) { // TODO Auto-generated constructor stub this.no = no; } public static Rate getRateByNo(Integer no) { switch (no) { case 0: return A; case 1: return B; case 2: return C; default: throw new IllegalArgumentException(); } } }
7、注解
1、注解
@Override限定重写父类方法,该注解只能用于方法
@Deprecated用于表示某个程序元素已过时
③SuppressWarnings抑制编译器警告
2、元注解
@Retention(存活周期)
RetentionPolicy.SOURCE(用于java文件)
RetentionPolicy.CLASS(用于class文件)默认的行为
RetentionPolicy.RUNTIME(用于运行时态)可以用于反射
@Target(可以用于修饰哪些程序元素)
TYPE
FIELD
METHOD
PARAMETER(形参)
CONSTRUCTORT
LOCAL_VARIABLE
@Documented(javadoc文档保留)
@Inherited(被修饰的注解具有继承性)
8、引用类型比较器
1、需要实现Comparable接口
2、Comparator接口脱离于类的比较器,自定义比较器