类,对象和接口
面向对象编程(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