将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
优点:
1只能通过规定的方法访问数据。
2隐藏类的实例细节,方便修改和实现。
1 public class HelloWorld { 2 private int a =1; 3 public int getA() { 4 return a; 5 } 6 public void setA(int a) { 7 this.a = a; 8 } 9 }
封装的实现步骤:
修改属性的可见性------private
创建getter/setter方法------用于属性读写
在getter/setter方法中加入属性控制语句(对属性值得合法性进行判断)
java中的包
包的作用 :管理java文件,解决同名文件冲突。
定义包:package包名(必须放在java源程序的第一行,包名间可以使用"."号隔开)
java中的访问修饰符
访问修饰符-----可以修饰实行和方法的访问范围
java的this关键字
1 this关键字代表当前对象:
this.属性 操作当前对象的属性。
this.方法 调用当前对象的方法。
2 封装对象的属性的时候,经常会使用this关键字
java中的内部类
内部类(InnerClass)就是定义在另外一个类里面的类,与之对应,包含内部类的类称为外部类
内部类的主要作用:
1 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类
2 内部类的方法可以直接访问外部类的所有数据,包括私有的数据
3 内部类所实现的功能使用外部类同样可以实现,只是使用内部类更方便
内部类的种类:
(1)在内部类中最常见的就是成员内部类,也称普通内部类
*内部类定义在外部类的内部,相当于外部类的一个成员变量的位置,内部类可以使用任意访问控制符,如public protected private等
1 package com.lx; 2 public class lx1 { 3 int a =1; 4 public void a1(){ 5 System.out.println("我是外部类的方法!"); 6 } 7 public class lx2{ 8 int a = this.a; 9 } 10 }
1 package com.lx; 2 import com.lx.lx1.lx2; 3 public class lx3 { 4 lx1 l1 = new lx1(); 5 lx2 l2 = new lx2(); 6 }
*内部类中定义的方法可以直接访问外部类中的数据不受访问控制符的影响,可以直接访问外部类中的私有属性
*定义了成员内部类后,必须使用外部类对象来创建内部类对象,而不能直接去new一个内部类对象
即:内部类 对象名= 外部类 对象.new 内部类();
*编译上面的程序后,就会发现产生了两个.class文件,内部类文件.class文件和外部类的.class文件
成员内部类的.class文件总是这样:外部类名$内部类名.class
注意:
外部类是不能直接使用内部类的成员变量和方法,可以先创建内部类的对象,然后通过内部类的对象来访问其成员变量和方法。
如果外部类和内部类具有相同的成员变量或方法,内部类默认访问自己的成员变量或方法,如果要访问外部类的成员变量或方法,可以使用this关键字。
(2)静态内部类
静态内部类是Static修饰的内部类,这种内部类的特点:
*静态内部类不能直接访问外部类的非静态成员,但可以通过"new 外部类()"成员的方式访问。
*如果外部类的静态成员与内部类的成员名称相同,可以通过"类名.静态成员"访问外部类的静态成员
如果外部类的静态成员与内部类的成员名不同,则可以通过"成员名"直接调用外部类的静态成员。
*创建静态内部类的对象时,不需要外部类的对象可以直接创建。
内部类 name = new 内部类();
(3)方法内部类
方法内部类就是内部类定义在外部类中的方法中,方法内部类只在该方法的内部可见,即只在该方法内可以使用。
注意:由于方法内部类不能再外部类的方法以外的地方使用,因此方法内部类不能使用访问控制符和Static修饰符。
(4)匿名内部类
匿名内部类也就是没有名字的内部类
正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写
但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
实例1:不使用匿名内部类来实现抽象方法
1 abstract class Person { 2 public abstract void eat(); 3 } 4 5 class Child extends Person { 6 public void eat() { 7 System.out.println("eat something"); 8 } 9 } 10 11 public class Demo { 12 public static void main(String[] args) { 13 Person p = new Child(); 14 p.eat(); 15 } 16 }
运行结果:eat something
可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用
但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?
这个时候就引入了匿名内部类
实例2:匿名内部类的基本实现
1 abstract class Person { 2 public abstract void eat(); 3 } 4 5 public class Demo { 6 public static void main(String[] args) { 7 Person p = new Person() { 8 public void eat() { 9 System.out.println("eat something"); 10 } 11 }; 12 p.eat(); 13 } 14 }
运行结果:eat something
可以看到,我们直接将抽象类Person中的方法在大括号中实现了
这样便可以省略一个类的书写
并且,匿名内部类还能用于接口上
实例3:在接口上使用匿名内部类
1 interface Person { 2 public void eat(); 3 } 4 5 public class Demo { 6 public static void main(String[] args) { 7 Person p = new Person() { 8 public void eat() { 9 System.out.println("eat something"); 10 } 11 }; 12 p.eat(); 13 } 14 }
运行结果:eat something
由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现
最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口
实例4:Thread类的匿名内部类实现
1 public class Demo { 2 public static void main(String[] args) { 3 Thread t = new Thread() { 4 public void run() { 5 for (int i = 1; i <= 5; i++) { 6 System.out.print(i + " "); 7 } 8 } 9 }; 10 t.start(); 11 } 12 }
运行结果:1 2 3 4 5
实例5:Runnable接口的匿名内部类实现
1 public class Demo { 2 public static void main(String[] args) { 3 Runnable r = new Runnable() { 4 public void run() { 5 for (int i = 1; i <= 5; i++) { 6 System.out.print(i + " "); 7 } 8 } 9 }; 10 Thread t = new Thread(r); 11 t.start(); 12 } 13 }
运行结果:1 2 3 4 5