一、内部类
1、内部类概述
内部类:讲一个类定义在了另一个类中,就是内部类,其实就是定义类的位置发生了变化。
在一个类中,定义在类中的叫成员变量,定义在方法中的叫成员方法,那么根据类定义的位置也可以分为
成员内部类和局部内部类
内部类产生的class文件为外部类$内部类
,为了标明该内部类是属于具体哪个外部类的
代码案例
package cn.com.example7;
public class OuterClass {
public static void main(String[] args) {
}
}
class Outer{
public String name = "外部类属性";
public void handlerOuterMethod(){
System.out.println("外部类方法");
}
// 定义内部类
class Inner{
public String name = "内部类属性";
public void handlerInnerMethod(){
System.out.println("内部类方法");
}
}
}
2、成员内部类访问方式
- 内部类可以直接访问外部类的成员属性
- 外部类需要访问内部类的成员属性时需要创建内部类的对象
- 在外部类的成员方法中创建内部类的对象,通过内部类的对象直接访问内部类的成员
- 在其他类中直接创建内部类的对象【Outer.Inner inner = new Outer().new Inner()】
代码案例
package cn.com.example7;
public class OuterClass {
public static void main(String[] args) {
// 实例化外部类对象
Outer outer = new Outer();
System.out.println(outer.handlerGetInnerField());
// 实例化内部类对象
Outer.Inner inner = new Outer().new Inner();
System.out.println(inner.innerName);
}
}
class Outer{
public String outerName = "外部类属性";
public void handlerOuterMethod(){
System.out.println("外部类方法");
}
// 定义内部类
class Inner{
public String innerName = "内部类属性";
public void handlerInnerMethod(){
System.out.println("内部类方法");
}
}
// 定义外部类方法用于获取内部类成员
public String handlerGetInnerField(){
return new Inner().innerName;
}
}
疑问:什么时候使用内部类?
当我们分析事物时,发现事物的内部还有具体的事物,这时则应该定义内部类
比如:人体是一个类,人体有心脏,心脏的功能在直接访问人体的其他内容,这时就将心脏定义在人体类中,作为内部类存在。
内部类的优势:成员内部类作为外部类的成员,那么可以访问外部类的任意成员。
3、成员内部类访问细节
成员内部类一旦私有化,只能在外部类类中实例化,在其他类中无法实例化成员内部类对象
代码案例
package cn.com.example7;
public class OuterClass {
public static void main(String[] args) {
// 实例化外部类对象
Outer outer = new Outer();
System.out.println(outer.handlerGetInnerField()); // 可以访问
// 实例化内部类对象
Outer.Inner inner = new Outer().new Inner(); // 不能访问
System.out.println(inner.innerName);
}
}
class Outer{
public String outerName = "外部类属性";
public void handlerOuterMethod(){
System.out.println("外部类方法");
}
// 定义私有内部类
private class Inner{
public String innerName = "内部类属性";
public void handlerInnerMethod(){
System.out.println("内部类方法");
}
}
// 定义外部类方法用于获取内部类成员
public String handlerGetInnerField(){
return new Inner().innerName;
}
}
如果内部类中包含有静态成员,那么java规定内部类必须声明为静态的,访问静态内部类的形式:Outer.Inner inner = new Outer.Inner();
代码案例
package cn.com.example7;
public class OuterClass {
public static void main(String[] args) {
// 实例化外部类对象
Outer outer = new Outer();
System.out.println(outer.handlerGetInnerField());
// 实例化内部类对象
Outer.Inner inner = new Outer.Inner();
System.out.println(inner.innerName);
}
}
class Outer{
public String outerName = "外部类属性";
public void handlerOuterMethod(){
System.out.println("外部类方法");
}
// 定义内部类
static class Inner{
public static String innerName = "内部类属性";
public void handlerInnerMethod(){
System.out.println("内部类方法");
}
}
// 定义外部类方法用于获取内部类成员
public String handlerGetInnerField(){
return Inner.innerName;
}
}
4、局部内部类
局部内部类:定义在外部类的方法中的类,称之为局部内部类
访问:可以在包含局部内部类的方法中直接实例化局部内部类的对象调用局部内部类的成员
代码案例
package cn.com.example7;
public class OuterClass1 {
public static void main(String[] args) {
new Outer1().handlerOuterMethodInnerClass();
}
}
class Outer1{
public String name = "外部类属性";
public void handlerOuterMethod(){
System.out.println("外部类方法");
}
public void handlerOuterMethodInnerClass(){
class InnerClass{
public String innerName = "局部内部类属性";
public void handlerInnerMethod(){
System.out.println("局部内部类方法");
}
}
// 访问局部内部类的成员
new InnerClass().handlerInnerMethod();
}
}
5、匿名内部类
匿名内部类:没有类名的内部类
匿名内部类作用:简化内部类书写
匿名内部类的前提:必须继承一个父类或者是实现一个接口
5.1、入门程序
语法:
new 父类或接口(){
代码块
}
代码案例
package cn.com.example7;
public class OuterClass2 {
public static void main(String[] args) {
new Outer2().handlerGetInnerClass();
}
}
// 匿名内部类接口
interface InterfaceInner{
void handlerMethod();
}
// 外部类
class Outer2 {
// 外部类方法调用匿名内部类方法
public void handlerGetInnerClass(){
new InterfaceInner(){
@Override
public void handlerMethod() {
System.out.println("匿名内部类方法");
}
}.handlerMethod();
}
}
5.2、匿名内部类调用多个方法
使用匿名内部类时,如果需要调用匿名内部类的两个方法或者两个方法以上,可以使用变量指向该对象。
代码案例
package cn.com.example7;
public class OuterClass2 {
public static void main(String[] args) {
new Outer2().handlerGetInnerClass();
}
}
// 匿名内部类接口
interface InterfaceInner{
void handlerMethod1();
void handlerMethod2();
}
// 外部类
class Outer2 {
InterfaceInner interfaceInner = new InterfaceInner() {
@Override
public void handlerMethod1() {
System.out.println("匿名内部类方法1");
}
@Override
public void handlerMethod2() {
System.out.println("匿名内部类方法2");
}
};
// 外部类方法调用匿名内部类方法
public void handlerGetInnerClass(){
interfaceInner.handlerMethod1();
interfaceInner.handlerMethod2();
}
}
二、包机制
当定义 了多个类的时候,可能会发生类名的重复问题,那么在java中可以采用包机制处理开发者定义的类名冲突问题
语法:
package 包名; // 指定该类所属于某个包下
代码案例
package cn.com.example7; // PackageClass类在cn.com.example7包【目录】下
public class PackageClass {
}
包的优点
- 防止类文件冲突
- 使源文件与类文件分离,便于软件最终发布
注意:
1、一个java类只能定义在一个包中
2、包语句肯定是描述类的第一条语句
包机制引发的问题
有了包之后,访问类时每次都需要把包名和类名写全 比如:
cn.com.example7.Outer outer = new cn.com.example7.Outer();
解决:使用import语句
语法:
import 包名.类名;
代码案例
package cn.com.example7;
import cn.com.example6.Father;
// 或者
import cn.com.example6.*;
public class PackageClass {
public static void main(String[] args) {
Father father = new Father();
}
}
1、如果想使用一个包中的许多类时,就不需要导入多条语句,使用*
号通配符代表所有的类
2、使用*
时不能导入包中的子类包的class文件
3、import语句可以是多条
三、访问修饰符
访问修饰符用来控制类、属性、方法的可见性的关键字,称之为访问修饰符。
1、访问修饰符概述
- public 一个类中,同一包下,子类中,不同包中
- protected 一个类中,同一包中,子类中
- default 一个类中,同一包中
- private 一个类中
public | protected | default | private | |
---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中 | √ | √ | √ | |
子类 | √ | √ | ||
不同包中 | √ |
2、修饰类成员
- 成员使用private修饰只在本类中使用
- 如果一个成员没有使用任何修饰符,就是default,该成员可以被包中的其他类访问
- protected成员被protected修饰可以被包中其他类访问,并且位于不同包中的子类也可以访问
- public修饰的成员可以被所有类访问
3、修饰类
- 类只有两种public和默认(成员内部类可以使用private)
- 父类不可以是private和protected,子类无法继承
- public类可以被所有类访问
- 默认类只能被同一个包中的类访问