前面一篇文章《JavaSE 拾遗(3)——JavaSE 面向对象程序设计语言基础(3) 》主要说了 java 应用程序的倒数第二层组成元素——函数,下面接着说 java 应用程序倒数第三层组成元素——类、对象,对象是类动态的概念,类的功能都要转化为对象才能实现。封装这里讲述了什么是封装,什么时候使用封装,如何定义一个类来实现封装。
先说一下面向对象的概念,面向对象是一种把这个世界看做为对象组成的思维方式。面向对象编程是把这个世界看做对象组成,并用面向对象的语言来描述我们对世界里的对象的认识的表达方式,我们认识这个对象的世界主要就是使用 简化、对比等抽象思维方式。面向对象语言中的封装、继承、多态就是这些思维方式的对应形式。
怎么学习面向对象编程
/**
需求:演示构造函数、构造代码块、默认初始化的先后顺序
思路:
步骤:
*/
public class Test{
private int i = 8;
{
i = 9;
}
public Test(){
i =10;
}
public static void main(String[] args) {
System.out.println(new Test().i);
}
}
javap 反汇编后:
/**
需求:演示 super 的jvm原理
思路:
步骤:
*/
public class Test extends Father{
public int i = 10;
public static void main(String[] args) {
new Test().println();
}
public void println(){
System.out.println(super.i);
}
}
class Father
{
protected int i = 12;
}
javap 反汇编结果:
/**
需求:演示 static 的原理
思路:
步骤:
*/
public class Test{
public static int i = 10;
static{
i = 11;
}
public static void main(String[] args) {
}
}
/**
需求:实现饿汉式单例设计模式
思路:用 static 把对象创建封装在类内部
步骤:
1.将构造函数私有化
2.在类中创建一个本类对象
3.提供一个可以方法可以获取到该对象
*/
class Single
{
private static Single single = new Single();
private Single()
{
}
public static Single getInstance()
{
return single;
}
}
class SingleDemo
{
public static void main(String[] args)
{
Single single = Single.getInstance();
System.out.println("Hello World!");
}
}
线程安全的懒汉式
/**
需求:实现线程同步的懒汉式单例设计模式
思路:用 static 把对象创建封装在类内部,延迟创建对象
步骤:
1.将构造函数私有化
2.提供一个可以获取到该类对象的方法,并既在第一次访问该方法的时候才创建对象,以后都是直接返回已经创建的对象
*/
class Single
{
private static Single single = null;
private Single()
{
}
public static Single getInstance()
{
if(single == null)
{
synchronized(Single.class)
{
if(single == null)
{
new Single();
}
}
}
return single;
}
}
class SingleDemo
{
public static void main(String[] args)
{
Single single = Single.getInstance();
System.out.println("Hello World!");
}
}
内部类的意思就是将类的定义放在另一个类的内部。有时合理的内部类使用会使代码更加简洁,令程序更加巧妙。作为外部类的成员,内部类可以访问外部类私有的成员变量。
静态内部类不可以使用外部类的非静态成员。当内部类中的成员为静态时,内部类必须为静态的。
局部内部类只能访问 final 修饰过的局部变量,因为非 final 局部变量存在于 java 栈的栈帧的局部变量表中,而内部类对象存在于堆中,所以内部类对象的生存周期可能比非 final 局部变量要长。更详细的介绍为什么内部类只能访问 final 修饰的局部变量,看这里
使 用匿名内部类应该注意:
a) 匿名内部类不能有构造方法
b) 匿名内部类不能定义任何静态成员、方法和类。
c) 匿名内部类不能是public,protected,private,static。
d) 只能创建匿名内部类的一个实例。
e) 一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
f) 因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
/**
需求:演示内部类
思路:成员访问的一些规则:
1.内部类 和 他的所属类 之间成员的相互访问,成员有重名的情况
2.其他外面的类 访问内部类的成员
内部类定义在外部类成员位置上的时候,可以用成员修饰符修饰。private static
静态内部类只能使用外部类的静态成员。内部内既然作为成员,那么就很少对外开
放了。
当内部类定义了静态成员,该内部类必须是 static 的。
匿名内部类,是局部内部类的一种简写形式。
步骤:
*/
class OutsideClass
{
private int v = 0;
//1.成员内部类演示,private 成员类用得较多
class InsideClass
{
int v = 1;
void function()
{
int v = 2;
System.out.print(v);
System.out.print(this.v);
System.out.print(OutsideClass.this.v); //打印结果是 210
}
}
//2.静态内部类演示
static class StaticInsideClass
{
int v = 1;
void function()
{
int v = 2;
System.out.print(v);
System.out.print(this.v);
//System.out.print(OutsideClass.this.v); //报错,只能访问外部类静态成员
}
}
void function()
{
//3.局部内部类,只能访问外面 final 变量
class LocalInsideClass
{
void function()
{
System.out.println("局部内部类");
}
}
//4.匿名内部类演示,用得较多,Comparator 就有使用
new OutsideClass()
{
void function()
{
System.out.println("匿名内部类");
}
}.function();
}
}
class InsideClassMain
{
public static void main(String[] args)
{
// 这种外部使用内部内创建对象的情况基本不使用,因为内部类一般都封装为 private 成员类
//OutsideClass.InsideClass part = new OutsideClass().new InsideClass();
OutsideClass part = new OutsideClass();
part.function();
}
}