内部类
-
局部内部类 (定义在方法中)
定义在方法中,内部类为局部内部类 局部内部类中只能定义非静态的成员内容,除了静态的常量 在局部内部类中可以使用所在外部类的成员 局部内部类中如果一旦使用所在方法的局部变量(参数),这个局部变量必须为常量 jdk7及之前 : 要求必须手动被final修饰 jdk8及之后 : 默认被final修饰 只能在所在的方法中通过对象访问局部内部类的成员,在外部类中的其他方法中|其他类中都无法使用局部内部类
public class Test01 { public static void main(String[] args) { class A{ int n; public A(){} public void m(){ System.out.println("我是局部内部类的一个m方法"); } } // 后续使用 A a = new A(); a.m(); } }
-
成员内部类 (定义在类中)
-
外部类使用内部类
-
创建对象 直接调用
-
-
内部类使用外部类
-
直接使用 内部类都会持有一个外部类对象的引用(
外部类.this
)
-
-
其他类使用外部类
-
一般不允许,所以我们会将内部类私有 防止外部访问
-
创建外部类对象.创建内部类对象 然后访问
-
外部类.内部类 变量 = new 外部类().new 内部类();
-
-
内部类定义在外部类的成员位置 可以被成员修饰符所修饰,可以继承其他父类,实现需要的接口,具有成员的特点,具有类的特点 特点 : 在成员内部类中只能定义非静态的成员内容,除了静态的常量 在成员内部类中可以直接使用所在外部类的成员,包括私有的 在所在外部类中需要通过成员内部类的对象访问其成员(包括私有成员),可以通过类名访问其静态的常量 在其他类中需要 通过外部类创建成员内部类对象,通过成员内部类对象访问其成员
package com.yjxxt.oop.inner; public class Test02 { public static void main(String[] args) { /* Outer01 outer01 = new Outer01(); outer01.m();*/ Outer01 outer01 = new Outer01(); System.out.println(outer01.n); /*Outer01.Inner01 inner01 = outer01.new Inner01(); inner01.fun();*/ } } class Outer01{ int n; public void m(){ System.out.println("outer01 m"); System.out.println(this.n); Inner01 inner01 = new Inner01(); inner01.fun(); } private class Inner01{ int m; public void fun(){ System.out.println("inner01 fun"); System.out.println(/*Outer01.this.*/n); } } }
-
静态内部类 (定义在类中 静态类)
-
外部类使用静态内部类
-
如果访问的是静态内部类中的静态内容: 类名.静态内容
-
如果访问的是静态内部类中的非静态内容: 创建对象访问
-
-
内部类使用外部类
-
创建对象访问
-
-
其他类使用外部类
-
一般不允许,所以我们会将内部类私有 防止外部访问
-
创建外部类对象.创建内部类对象 然后访问
外部类.内部类 变量 = new 外部类().new 内部类();
-
被static修饰的内部类 静态内部类中可以根据需求定义静态|非静态的成员 在静态内部类中可以直接使用所在外部类的静态内容,需要通过外部类的对象访问其成员 在所在外部类中可以通过类名访问静态内部类中静态内容,需要通过对象访问静态内部类中的成员 在其他类中可以通过外部类类名.内部类类名.静态内容访问静态内部类中的静态内容 在其他类中可以通过new 外部类类名.内部类类名()的内部类对象访问静态内部类中的成员内容
package com.yjxxt.oop.inner; public class Test03 { public static void main(String[] args) { /* Outer02 outer02 = new Outer02(); outer02.fun();*/ // Outer02.Inner02.m(); // new Outer02.Inner02(); System.out.println(Outer02.m); /* Outer02.Inner02 inner02 = new Outer02.Inner02(); System.out.println(inner02.n);*/ } } class Outer02{ static int m; public void fun(){ System.out.println("outer fun"); // 如何使用内部类中的内容 System.out.println(m); Inner02 inner02 = new Inner02(); System.out.println(inner02.n); Inner02.m(); } static class Inner02{ int n; public void method(){ System.out.println("inner method"); new Outer02().fun(); } public static void m(){ System.out.println("inner m"); } } }
私有内部类 :
被private修饰的成员内部类
私有内部类中可以直接使用外部类的成员,包括私有的
在所在外部类中,通过私有内部类的对象访问其成员
其他类中无法使用私有内部类
-
匿名内部类 (定义在方法中)
简化一些满足条件要求的实现类|子类,将定义实现类重写方法+创建实现类对象两步合并成一步 1)类没有自己本身作用 2)实现类|子类只在当前使用一次,不会重复使用多次 语法 : new 接口|抽象类(){--->实现类|子类类体 重写方法.... };
public class Class006_Outer {
public static void main(String[] args) {
//定义接口实现类
//Demo demo = new Demo();
//demo.swimming();
//匿名内部类对象使用方式一 : 匿名对象-->对象只能在当前使用一次
new Swim(){
@Override
public void swimming() {
System.out.println("花样游泳....");
}
}.swimming();
//匿名内部类对象的使用方式二 : 引用指向对象
AbsClass abs = new AbsClass(){
@Override
void absMethod(boolean flag) {
System.out.println("抽象类的子类"+flag);
}
};
abs.absMethod(false);
abs.absMethod(true);
//匿名内部类使用方式三 : 作为方法的实参
testSwim(new Swim() {
@Override
public void swimming() {
System.out.println("仰泳...");
}
});
}
//游泳俱乐部,入场的都要会游泳的
public static void testSwim(Swim swim){ //当方法的形参为一个接口类型,方法的实参就要为接口的实现类对象
swim.swimming();
}
}
//接口
interface Swim{
void swimming();
}
//实现类
class Demo implements Swim{
@Override
public void swimming() {
System.out.println("狗刨....");
}
}
abstract class AbsClass{
abstract void absMethod(boolean flag);
}
lambda表达式 : *****
jdk1.8新特性之一
作用 : 简化满足条件的匿名内部类对象
前提 : 函数式接口
函数式接口 : 抽象方法只有一个
如何检查一个接口是否为函数式接口 : @FunctionalInterface
语法 :
()->{}
() : 重写方法的参数列表
-> : 箭头函数 | lambda符号
{} : lambda体-->重写方法的方法体
注意 :
以后看到方法的形参|引用的引用的类型为函数式接口的时候,那么传递实参|为引用赋值就可以通过lambda表达式进行实现
public class Class001_Lambda {
public static void main(String[] args) {
//匿名内部类对象
/*Smoke s = new Smoke(){
@Override
public void smoking() {
System.out.println(".....");
}
};*/
//lambda 写法1 : 标准写法
/*Smoke s = () -> {
System.out.println(".....");
};*/
//lambda 写法2 : 当lambda体中语句只有一句,前后的{}可以省略
//Smoke s = () -> System.out.println("边抽烟会吐烟圈...");
//lambda 写法3 : 当抽象方法存在参数,参数的数据类型可以省略
//Smoke s = (name,age) -> System.out.println("边抽烟会吐烟圈..."+age);
//lambda 写法4 : 当抽象方法存在参数且参数只有一个,前后的()可以省略
//Smoke s = a -> System.out.println("边抽烟会吐烟圈..."+a);
//lambda 写法5 : 当抽象方法存在返回值,lambda体中语句只有一句,且是return带出返回值语句,前后的{}与return关键字可以一起省略
//Smoke s = age -> age>=18;
//System.out.println(s.smoking(19));;
testSmoke(new Smoke() {
@Override
public boolean smoking(int age) {
return false;
}
});
testSmoke(age->age>=18); //函数式编程
//将方法的实现作为参数传递
}
static void testSmoke(Smoke smoke){
smoke.smoking(20);
}
}
//接口
@FunctionalInterface
interface Smoke{
boolean smoking(int age);
//静态方法
static void testStatic(){}
default void testDefault(){}
}
包和导包
包
package com.yjxxt.oop.ext; // 通过package指定当前类所属的包 这行代码一定是一个类的首行
1: 为什么需要创建包? 为什么在创建类的时候需要给当前类指定包?
区分不同的类,管理不同的类。
2:如何创建一个包?
详细请看标识符。 一般命名规则: 公司域名倒着写 com.yjxxt 项目名称: 学生管理系统 .ss 模块名称: 学生模块 .student 子模块名称... com.yjxxt.ss.student.view.....
3: 如何确定一个类?
确定类的方式: 全限定名 包名.类名 com.yjxxt.oop.ext.Test02
导包
导包就是为了使用类。在使用类的时候需要通过包名.类名去确定。
-
java.lang包下的所有类是不需要导入的
-
jdk1.7
之后支持静态导入,可以不需要写类名,直接使用方法或者是变量。import static 包名.类名.*; // 导入指定包下的指定类中的所有静态内容
-
如果需要导入同名类,此时一个通过导入的方式,一个需要通过全限定名去使用。
import java.util.Date; main(){ Date d = new Date(); // java.util.Date java.sql.Date date = new java.sql.Date(1L); }
权限修饰符/位置 本类 同包子类 同包异类 异包子类 异包异类 public √ √ √ √ √ protected √ √ √ √ × 默认的 不写 √ √ √ × × private √ × × × ×