三、类,对象和接口

来源:互联网 发布:九章算法班视频 编辑:程序博客网 时间:2024/04/29 05:45

类,对象和接口

面向对象编程(Object Oriented Programming) OOP:
封装/继承/多态

对象初始化过程:
参考:http://swiftlet.net/archives/1049;
http://blog.sina.com.cn/s/blog_86e34ca801014lex.html;
对象类:

class Person {private static Person person= new Person();public  static int count1;public  static int count2 = 5;public int count3;static {    System.out.println("[静态初始化块]count2="+count2);    System.out.println("[静态初始化块]person="+person);}private Person() {    count1++;    count2++;    System.out.println("[执行Person构造函数]count1="+count1);    System.out.println("[执行Person构造函数]count2="+count2);} public static Person getInstance()   {          return person;   }{        System.out.println("[初始化块]count3="+count3);        System.out.println("[初始化块]person="+person);}public Person(int count){    this.count3=count;    System.out.println("[构造函数初始化]count3="+count3);}}

测试类:
public class Test
{

public static void main(String[] args){        System.out.println("[新建变量]person");        Person person;        System.out.println("[执行构造函数导致变量初始化]");        person= new Person(10);            System.out.println("[执行类的静态函数]");        Person.getInstance();}}

运行结果:
1[新建变量]person
2[执行构造函数导致变量初始化]
3[初始化块]count3=0
4[初始化块]person=null
5[执行Person构造函数]count1=1
6[执行Person构造函数]count2=1
7[静态初始化块]count2=5
8[静态初始化块]person=Person@757aef
9[初始化块]count3=0
10[初始化块]person=Person@757aef
11[构造函数初始化]count3=10
12[执行类的静态函数]

分析如下:
1、根据程序运行顺序,输出语句1;
2、声明Person类对象。要注意一点:程序编译后会加载所有类的字节码文件,而在使用到某个类的时候会将字节码文件加载到内存中。此时会优先给类中静态变量分配空间(person,count1,count2)和默认初始值(不是程序里面的赋值语句)。
此处还需注意,静态变量中,如private static Person person= new Person(); 应该明确分为声明和初始化两部分:

private static Person person;static{person = new Person();}

其中初始化部分以静态代码块的形式表示。而类中所有静态代码块在编译时会合并成一个静态代码块,Person类等同如下:

class Person {private static Person person;staitc{person = new Person();}public  static int count1;public  static int count2 ;static{count2 = 5;}public int count3;static {    System.out.println("[静态初始化块]count2="+count2);    System.out.println("[静态初始化块]person="+person);}}

最终合并如下:

class Person {private static Person person;public  static int count1;public  static int count2 ;public int count3;static     {person = new Person();    count2 = 5;    System.out.println("[静态初始化块]count2="+count2);    System.out.println("[静态初始化块]person="+person);    }}

在执行Person person时,只对person对象做了声明,而不会运行静态代码块。因此无输出。此时静态变量已经有了内存地址,而且已经有了默认值:object为null,int为0(此时count2值为0,count2 = 5语句暂不执行)。
3、根据程序运行顺序,输出语句2;
4、执行person= new Person(10);
初始化顺序为:父类静态变量-子类静态变量-父类静态代码块-子类静态代码块-父类成员变量-父类构造代码块-父类构造函数-子类成员变量-子类构造代码块-子类构造函数。
首先由于静态变量在上面已经声明了(已有内存空间),因此会执行静态代码块:
1:person = new Person();
这步会调用构造函数,因为有构造代码块,所以先执行构造代码块后执行构造函数。构造代码块输出语句3和4(count默认为0,person对象还没有执行到构造函数,因此为null)。构造函数执行无参的输出语句5和6(此时静态代码块中正在执行语句person = new Person(),而count1和count2的赋值语句其实实在person = new Person()后执行的,因此此时两个值都是0,执行++后输出结果为1)。
2:count2 = 5;
此时count2变为5;
3:System.out.println(“[静态初始化块]count2=”+count2);
System.out.println(“[静态初始化块]person=”+person);
输出语句7和8。(count2为5,person已分配到内存)

至此,静态代码块执行完毕。
然后执行构造代码块,输出语句语句9和10。
最后执行有参构造方法,输出语句11。
5、回到主函数,执行语句12。

分析完毕。

  • 方法重载为同名方法不同参数,是多态性的一种。
  • 构造方法不能用static修饰。
  • 重载构造方法后默认的构造方法将不再提供。
  • 类方法(static)只能操作类变量(static)。
  • 类方法只能调用该类的类方法,不能调用实例方法。
  • 实例方法在创建第一个对象时分配入口地址,之后创建对象不再分配。当所有对象都不存在时会被销毁。而类方法在编译加载到内存中时已分配到入口地址。其中局部变量每次重新生成,执行完立即销毁。
  • this关键字不能出现在类方法中。
  • 对象创建时,会默认为成员变量初始化:int为0,float为0.0f,boolean为false,object为null。局部变量必须手动初始化。
  • 两个对象p1,p2。执行p1=p2后,p1原来的内存会被马上释放掉(gc回收),同时引用指向p2的内存。
  • java传值:
    1、基本数据类型:传副本,不影响原本的值。
    2、引用数据类型:对象,数组,以及接口,传递引用,修改原本数据。
  • import引入这个包,会增加编译时间,但是不会影响性能。(只有使用到的类才会加载到内存中)
  • 访问权限:
    1、public:所有类都能访问。
    2、protected:同包可访问。子类可访问。(如果存在继承关系,那么需要判断该属性或方法的创建者与调用者是否在同包。如B类继承A类,C类中创建B类对象,此时调用B中的protected属性,如果该属性是B自己声明的,则判断B类与C类是否同包,如果是从A类继承过来的,则判断A类与C类是否同包)
    3、friendly不用修饰符修饰:友好。同包可访问子类不可访问。
    4、private:只有自己访问。
  • 成员变量和方法重写可以隐藏父类属性和方法,需要通过super调用父类属性方法,需要注意重写时访问权限不能低于父类访问权限。
  • final修饰的类不能被继承。
  • 子类B继承父类A,则a=b为向上转型。其中a失去B新增的方法和变量,并且会优先访问子类继承的属性和重写的方法。
  • 多态是指父类被多个子类重写后,可以通过向上转型产生各自的行为。
    abstract类中可以有abstract方法,也可以没有,abstract方法不能用final修饰(用于继承),而且不能有方法体。abstract方法只能存在abstract类中。
  • 构造方法中,子类的构造方法super.构造函数必须放在第一行。
  • 接口中方法默认public abstract,变量默认public static。所以实现时一定要用public修饰方法。
  • 内部类中不可以声明类成员和类方法,外部类可以用内部类声明对象。
  • 匿名类一定是内部类,不能声明static成员变量和static方法
  • throws在方法上声明可能抛出的异常,throw用于捕获后抛出异常。
  • 获取类相关信息:getName、getDeclaredConstructors、getDeclaredFields、getDeclaredMethods
  • 对象创建两种方法:1、通过new;2、通过Class类。
    如class A{},可以用Class cs = Class.forName(“A”);
    A a = (A)(cs.newInstance());创建对象。
  • 反编译:sdk自带javap.exe
0 0
原创粉丝点击