内部类
什么事内部类
将一个类定义在另一个类里面或者一个方法里面,这样的类成为内部类。
内部类的分类
成员内部类,局部内部类,匿名内部类和静态内部类
成员内部类
成员内部类是普通的内部类,它的定义位于另一个类的内部。
成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
成员内部类格式
class 外部类 {
class 内部类{
}
}
成员内部类访问特点
内部类可以直接访问外部类的成员,包括私有成员
外部类要访问内部类的成员,必须创建内部类对象才能访问
内部类访问外部类的同名成员
外部类.this.成员变量
外部类.this.成员方法
内部类可以拥有private,protected,public访问权限
创建内部类对象格式
外部类名.内部类名 对象名 = new 外部类型().new 内部类型();
代码演示
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/13 16:36
*/
public class Person {
private boolean live = true;
class Heart{
public void jump(){
if (live){
System.out.println("心脏跳动");
}else {
System.out.println("心脏停止");
}
}
}
public boolean isLive() {
return live;
}
public void setLive(boolean live) {
this.live = live;
}
}
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/13 16:08
*/
public class test01 {
public static void main(String[] args) {
//调用内部类方法 法一
//创建外部类对象
Person person = new Person();
//创建内部类的对象
Person.Heart heart= person.new Heart();
//调用内部类方法
heart.jump();
//调用外部类方法
person.setLive(false);
//调用内部类方法
heart.jump();
/* Person.Heart heart = new Person().new Heart();
heart.jump();*/
}
}
内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。例如:Person$Heart.class
局部内部类
局部内部类的定义
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问权限仅限于方法内或者该作用域内
如何使用局部内部类
只能在该方法内部使用局部内部类
代码演示
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/13 16:49
*/
public class Outer {
public void show(){
//局部内部类
class Inner{
public void method(){
System.out.println("局部内部类的method方法执行了....");
}
}
//在外部类的方法内使用局部内部类
Inner inner = new Inner();
inner.method();
}
}
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/13 16:47
*/
public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
outer.show();
}
}
匿名内部类
匿名内部类是内部类的简化写法,它的本质是一个带具体实现的父类或者父接口的匿名的子类对象
使用匿名内部类的前提
匿名内部类必须有继承父类或者实现一个父接口
匿名内部类的格式
new 父类名或者接口名(){
// 方法重写
@Override
public void method() { // 执行语句
}
};
代码实现
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/13 16:58
*/
public abstract class Animal {
public abstract void eat();
}
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/13 16:58
*/
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃狗粮");
}
}
public interface Person {
void study();
}
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/13 17:02
*/
public class Test {
public static void main(String[] args) {
//创建一个匿名内部类对象
new Animal() {
@Override
public void eat() {
System.out.println("啥也不吃,饿着");
}
}.eat();
//创建接口匿名内部类对象
new Person() {
@Override
public void study() {
System.out.println("好好学习");
}
}.study();
//匿名对象:就是没有名字的对象
//只是用一次对象的时候,可以使用匿名对象,如果想使用多次,必须给该对象起个名字
//通过对象名.方法名();重复调用
}
}
引用类型方法的参数和返回值
class作为方法的参数及返回值
类名作为方法的参数
方法的形参是类名,其实需要的是该类的对象
实际传递的是该对象的【地址值】
类名作为方法的返回值
方法的返回值是类名,其实返回的是该类的对象
实际传递的,也是该对象的【地址值】
代码演示
package 引用类型方法的参数和返回值.class作为方法的参数及返回值;
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/13 17:24
*/
public class Student {
private String name;
private int age;
private PC pc;
public Student(String name, int age, PC pc) {
this.name = name;
this.age = age;
this.pc = pc;
}
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public PC getPc() {
return pc;
}
public void setPc(PC pc) {
this.pc = pc;
}
public void show(){
System.out.println("姓名:"+name+"\t年龄:"+age);
}
public void usePcWork(){
// 姓名为: 张三 , 年龄:13岁 正在使用: 外星人,价格: 135000, 颜色为:黑色的电脑,在疯狂的斗地主
System.out.println(" 姓名为: "+name+" , 年龄:"+age+"岁 正在使用: "+pc.getBrand()+
",价格: "+pc.getPrice()+", 颜色为:"+pc.getColor()+"的电脑,在疯狂地gank");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package 引用类型方法的参数和返回值.class作为方法的参数及返回值;
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/13 18:41
*/
public class PC {
private String brand;
private int price;
private String color;
public PC() {
}
public PC(String brand, int price, String color) {
this.brand = brand;
this.price = price;
this.color = color;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
package 引用类型方法的参数和返回值.class作为方法的参数及返回值;
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/13 18:43
*/
public class MethodArgsClassTest {
public static void main(String[] args) {
PC pc = new PC("曼巴狂蛇", 8000, "银色");
System.out.println(pc);
usePC(pc);
System.out.println("%%%%%%%%%%%%%%%");
PC pc1 = getPC();
System.out.println(pc1);
System.out.println(pc1.getBrand());
System.out.println(pc1.getPrice());
System.out.println(pc1.getColor());
}
// 定义一个方法,实现获取一台电脑
public static PC getPC(){
PC pc = new PC("雷蛇", 8000, "灰色");
System.out.println(pc);
return pc;
}
// 定义一个方法,来使用PC电脑
public static void usePC(PC pc){
System.out.println(pc);
System.out.println(pc.getBrand());
System.out.println(pc.getPrice());
System.out.println(pc.getColor());
}
}
package 引用类型方法的参数和返回值.class作为方法的参数及返回值;
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/13 18:51
*/
public class MethodArgsClassTest1 {
public static void main(String[] args) {
/*
class作为成员存在
一个学生,有一台笔记电脑,用电脑实现学生在使用电脑
该案例中,有两个事物存在
一个事物是学生
一个事物是电脑
学生在使用电脑,电脑是属于学生的
电脑做为学生类的一个成员而存在的
*/
PC pc = new PC("狂蛇", 12000, "银灰色");
Student student = new Student("小明", 14);
student.setPc(pc);
student.usePcWork();
}
}
package 引用类型方法的参数和返回值.class作为方法的参数及返回值;
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/13 17:27
*/
public class Test {
public static void main(String[] args) {
Student s = new Student("张三", 14);
System.out.println(s);
useStudent(s);
System.out.println("@@@@@@@@@@@@@@");
Student student = getStudent();
System.out.println(student);
student.show();
}
//类名作为方法的返回值和参数
public static void useStudent(Student student){
System.out.println(student);
student.show();
}
public static Student getStudent(){
Student student = new Student("李四", 20);
System.out.println(student);
return student;
}
}
抽象类作为方法的参数及返回值
抽象类作为方法的参数和返回值
方法的形参是抽象类名,其实需要的是该抽象类的子类对象
方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
代码演示
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/14 14:59
*/
public abstract class Animal {
public abstract void eat();
}
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/14 14:59
*/
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/14 15:01
*/
public class AnimalDemo {
public static void main(String[] args) {
Animal animal = getAnimal();
animal.eat();
Animal animal1 = new Cat();
useAnimal(animal1);
}
/**
* 抽象类作为方法的参数
*/
public static void useAnimal(Animal animal){
animal.eat();
}
/**
* 抽象类作为返回值
* @return
*/
public static Animal getAnimal(){
Animal animal = new Cat();
return animal;
}
}
接口作为方法的参数及返回值
接口作为形参和返回值
方法的形参是接口名,其实需要的是该接口的实现类对象
方法的返回值是接口名,其实返回的是该接口的实现类对象
代码演示
public interface Jumpping {
public void jump();
}
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/14 15:06
*/
public class Cat implements Jumpping {
@Override
public void jump() {
System.out.println("猫吃鱼儿");
}
}
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/14 15:07
*/
public class Test {
public static void main(String[] args) {
Jumpping jumpping = new Cat();
jumpping.jump();
Jumpping jumpping1 = new Cat();
useAnimal(jumpping1);
}
/**
* 接口作为返回参数
* @return
*/
public static Jumpping getAnimal(){
Jumpping jumpping = new Cat();
return jumpping;
}
/**
* 接口作为方法参数
* @param jumpping
*/
public static void useAnimal(Jumpping jumpping){
jumpping.jump();
}
}
final关键字
final:不可改变。可以用于修饰类,方法和变量
类:被修饰的类,不能被继承
方法:被修饰的方法,不能被重写
变量:被修饰的变量,不能被重新赋值
修饰类格式
final class 类名 {
}
修饰方法格式
修饰符 final 返回值类型 方法名(参数列表){
//方法体
}
修饰变量
局部变量--基本类型
基本类型的局部变量,被final修饰后,只能赋值依次,不能再更改
public class FinalDemo1 {
public static void main(String[] args) {
// 声明变量,使用final修饰
final int a;
// 第一次赋值
a = 10;
// 第二次赋值
a = 20; // 报错,不可重新赋值
// 声明变量,直接赋值,使用final修饰
final int b = 10;
// 第二次赋值
b = 20; // 报错,不可重新赋值
}
}
局部变量--引用类型
引用类型的局部变量,被final修饰后,只能指向一个对象,地址值不能更改。但是可以修改对象内部的值
final int[] arr = {10,20,30};
System.out.println(Arrays.toString(arr));
arr[0]=8;
System.out.println(Arrays.toString(arr));
权限修饰符
public | protected | default(空的) | private | |
---|---|---|---|---|
同一个类中 | √ | √ | √ | √ |
同一包中(子类与无关类) | √ | √ | √ | |
不同包的子类 | √ | √ | ||
不同包中的无关类 | √ |
static关键字
它可以用来修饰成员变量和成员方法,被修饰的成员属于类的,而不是单单属于某个对象的。也就是说,既然属于类,就可以不靠创建对象来调用
static定义变量
类变量:使用static关键字修饰的成员变量
当static修饰成员变量时,该变量成为类变量。该类的每个对象都共享同一个类变量的值。任何对象都可以更改该变量的值,但也可以不创建该类的对象的情况下对类变量进行操作。
定义格式
static 数据类型 变量名
static定义方法
类方法:使用static关键字修饰的成员方法,习惯称为静态方法
当static修饰成员方法时,该方法成为类方法。静态方法在声明中有static,建议使用类名来调用,而不需要创建类的对象。
定义格式
修饰符 static 返回值类型 方法名 (参数列表){
// 执行语句
}
注意事项
静态方法可以直接访问类变量和静态方法
静态方法不能直接访问普通成员变量或成员方法。成员方法可以直接访问类变量或静态方法
静态方法中,不能使用this关键字
调用格式
//被static修饰的成员可以并且建议通过**类名直接访问**。
//虽然也可以通过对象名访问静态成员,原因即多个对象均属
//于一个类,共享使用同一个静态成员,但是不建议,会出现警告信息
// 访问类变量
类名.类变量名;
// 调用静态方法
类名.静态方法名(参数);
static总结
被static修饰的内容
是随着类的加载而加载的,之加载一次
存储于一块固定的内存区域(静态区),所以,可以直接被类名调用
它由于对象存在,所以,可以被所有对象共享
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/14 16:03
*/
public class Student {
private String name;
private int age;
//只要加上static关键字它们都属于共享数据,而不是属于某一个对象的数据
static String schoolName;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/14 16:05
*/
public class Test {
public static void main(String[] args) {
//通过类名,静态成员变量名
Student.schoolName="郸城一高";
Student student = new Student();
student.setName("小明");
student.setAge(20);
System.out.println(student.getName());
System.out.println(student.getAge());
System.out.println(Student.schoolName);
}
}
静态代码块
定义在成员为止,使用static修饰的代码块{}。
位置:类中方法外
执行:随着类的加载而且只执行一次,优先于main方法和构造方法的执行
格式
public class ClassName{
static {
// 执行语句
}
}
代码演示
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/14 16:19
*/
public class Student {
static {
System.out.println("静态代码块");
}
public Student(){
for (int i = 0; i < 10; i++) {
System.out.println("HI 你好!");
}
System.out.println("无参构造");
}
public Student(int num ){
System.out.println("有参构造");
}
}
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/14 16:21
*/
public class Test {
public static void main(String[] args) {
Student student = new Student();
System.out.println("$$$$$$$$$$$$$$$");
Student student1 = new Student(8);
System.out.println("&&&&&&&&&&&&&&&&");
for (int i = 0; i < 8; i++) {
Student student2 = new Student();
}
}
}
匿名内部类面试笔试题
interface Inter {
void show();
}
class Outer {
//补齐代码
}
public class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}
要求在控制台输出”HelloWorld”
解答代码
public interface Inner {
void show();
}
/**
* @Describe
* @Author Double LiFly
* @date 2021/4/13 19:58
*/
public class Outer{
//方法一 匿名内部类解题
/* public static Inner method(){
return new Inner() {
@Override
public void show() {
System.out.println("hello world");
}
};
}*/
//方法二 接口作为返回参数解题
//定义一个静态类 InnerImpl实现Inner接口里的show方法
public static class InnerImpl implements Inner{
@Override
public void show() {
System.out.println("hello world");
}
}
/**
* 创建InnerImpl对象并返回
* @return
*/
public static InnerImpl method(){
InnerImpl innerImpl = new InnerImpl();
return innerImpl;
}
}
public class OuterDemo {
public static void main(String[] args) {
Outer.method().show();
}
}