JavaSE---------基础知识点08(面向对象大整合(下))

面向对象

一、基本的面向对象

1.面向对象的设计思想

在现实世界生活:

类:抽象的概念,把具有相同特征和操作的事物归为一类

先有实体,再有类的概念

在我们代码的世界里:

类:抽象的概念,把具有相同属性和方法的对象归为一列

编写顺序:先有类,再创建对象

类的作用:类相当于一个模板,刻画出具有相同属性和方法的对象

2.面向对象和面向过程的区别

面向对象:

是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。

面向过程:

就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了

3.类与对象的关系

一个类可以有多个对象

类包含于对象,有类才能有对象。

比如:种群的划分,就是一个类,指定与其中一个,即为对象

//测试
public class Test{
	//学生类
	class Student(){
	//属性
	String name;
	char sex;
	int age;
	
	}
	public static void main(String[] args){
       //创建对象
       //学生类   对象1   新建  类名();
		Student student=new Student();
        //给属性赋值
		student.name="榮十一";
		student.sex='男';
		student.age=22;
        //输出
		System.out.println(student.name);
		System.out.println(student.sex);
		System.out.println(student.age);
	}
}
3.1类的定义

给一切事物的名称的定义

3.2类中成员变量的定义

语法结构: 数据类型 变量名

3.3类中方法的定义

语法结构: 访问修饰符 返回值类型 方法名[参数]{ 代码块 }

3.4对象的定义

给某一个人或者某一件物定义名称

如:创建了一个人类,给他取名为:小明,小明拥有的功能和作用等

3.5对象的创建

类名 对象名 = new 类名();

3.6对象调用成员变量及方法
3.6.1 成员变量 VS 局部变量

成员变量:使用于类中,方法的外面的变量,并且系统会默认赋值,作用于整个类中。

整数类型 默认为0;浮点类型 默认为0.0; char类型 默认为空格(' '; Boolean类型 默认为false ;   String类型默认为null
public class Test{

    public static void main(String[] args){
        Test01 t=new Test01();
        t.name="姓名";
        System.out.println(t.name);
        t.mehtod01();
    }
    static class Test01{
        String name;
        char sex;
        int age;
        public void mehtod01(){
            double score=99.0;
            System.out.println("局部变量的成绩为"+score);
        }
    }
}

局部变量: 作用于方法内的变量,系统不会赋予默认值,作用在方法中

3.6.2成员方法 VS 静态方法

成员方法:属于对象的方法,必须使用对象调用

静态方法:属于类的方法,使用类名调用

public class Test{

	public static void main(String[] args){
		Test t=new Test();
		t.method01();
		Test.method02();
	}
	public void method01(){
		System.out.println("这个是成员方法");
	}
	public static void method02(){
		System.out.println("这个是静态方法");
	}
}
3.6.3成员变量 VS静态变量

成员变量:属于对象的变量,每个对象独享一份

静态变量:属于类的变量,每个对象都共享一份

public class A{
//成员变量
String str1;
//静态变量
static String str2;
}
public class TestA{
	public static void main(String[] args){
		A a1=new A();
		A a2=new A();
		a1.str1="aaa";
		a2.str1="bbb";
		System.out.println(a1.str1);
		System.out.println(a2.str1);
		A.str2="ccc";
		A.str2="ddd";
		System.out.println(a1.str2);
		System.out.println(a2.str2);
	}
}

4.构造方法

  1. 与类名相同的方法
  2. 没有返回项
4.1构造方法的定义

与类名相同,且没有返回项的方法

4.2构造方法的使用
  1. 和new在一起是创建对象
  2. 初始化属性
4.3构造方法的重载
public class Person{
	String name;
	char sex;
	int age;
	//构造方法
	public Person(){}
	//构造方法的重载
	public Person(String name,char sex,int age){
		this.name=name;
		this.sex=sex;
		this.age=age;
	}
}
4.4构造方法与普通方法的区别

构造方法:必须与类名相同,且没有返回项

普通方法: 可以与类名相同,可以有返回项

public class Person{
	//注意:这种不是构造方法,而是成员方法
	public void Person(){}
}

二、面向对象特性之封装

1.private的使用

可以作用于方法、属性上,进行私有化

应用场景: 不让外界调用的属性和方法就使用private修饰

2.get/set方法的说明

get()方法,作用于得到私有化输出

set()方法,作用于设置私有化,以便get方法来得到数据

三、this关键字

代表本对象,this出现方法里,表示调用该方法的对象

this.属性/方法:调用本对象的成员变量/方法

this():调用本对象的构造方法(在一个构造方法中的第一句调用另外一个构造方法)

1.静态属性

静态属性属于类属性,该类所有的对象都共享该属性,静态属性直到项目结束才会被回收

注意:静态属性使用类名调用

static String name;

2.静态方法

public class A{
    public static void main(String[] args){
        A a=new A();
        A.method();
    }
	public static void method(){
        System.out.println("静态方法");
    }
}

注意:静态方法只能使用类名调用;

3.静态代码块

静态代码块是类加载到方法区时才会被调用,该代码块只能初始化静态变量

代码块是创建对象时优先于构造方法调用,该代码块可以初始化成员变量和静态变量

构造方法是创建对象时调用,该方法可以初始化成员变量和静态变量 ​

public class A{
	static Sting name;
	static {
	name="xxx";//A.name
	System.out.println("A的静态代码块")
	}
}

四、继承

1.继承的概念

子类继承父类,一个子类只能有一个父类,一个父类可以有多个子类

2.类的继承的使用

多个类似的类,有相同的属性和方法,就可以把相同的属性和方法,抽取到父类,从而减少了代码的冗余性

创建子类对象,会不会调用父类构造方法?

创建子类对象,会不会创建父类对象?
不会
创建子类对象,为什么会调用父类构造方法?
目的是在子类对象中开辟空间用于存放父类的属性

创建子类对象,先调用父类构造方法还是子类构造方法?
先调用子类构造方法

创建子类对象,先完成父类构造方法还是子类构造方法?
先完成父类构造方法

子类可以继承父类私有化的属性和方法吗?

​ 可以继承,但是不可以直接调用,但是可以在父类中设置公有的方法,在公有的方法中调用私有的属性和方法,这叫做间接调用

3.继承中的构造方法

public class Person {
	
	String name;
	char sex;
	int age;
	
	public void eat(){
		System.out.println("吃饭饭");
	}
	
	public void sleep(){
		System.out.println("睡觉觉");
	}

}
public class Chinese extends Person{

	String chineseId;
	
	public void playTaiJi(){
		System.out.println("打太极");
	}
}
public class Japanese extends Person{

	String yearNumber;
	
	public void playVideo(){
		System.out.println("拍电影");
	}
}
public class Test{
	public static void main(String[] args) {
		/**
		 * 知识点:继承
		 * 含义:子类继承父类的属性和方法
		 * 好处:减少代码冗余
		 * 应用场景:多个类中有相同的属性和方法,就抽取出放在父类里
		 * 
		 * 需求:编写中国人、日本日
		 * 分析:
		 * 	中国人 继承 人类:
		 * 		属性:中国人的身份证
		 * 		方法:打太极
		 * 	日本人 继承 人类:
		 * 		属性:年号
		 * 		方法:拍电影
		 * 	人类:
		 * 		属性:姓名、性别、年龄
		 * 		方法:吃饭饭、睡觉觉
		 */
		
		Chinese c = new Chinese();
		//操作父类属性
		c.name = "榮十一";
		c.sex = '男';
		c.age = 21;
		System.out.println(c.name);
		System.out.println(c.sex);
		System.out.println(c.age);
		//操作子类属性
		c.chineseId = "1234567890";
		System.out.println(c.chineseId);
		//调用父类方法
		c.eat();
		c.sleep();
		//调用子类方法
		c.playTaiJi();
		
		Japanese j = new Japanese();
		//操作父类属性
		j.name = "美田桜奈汾";
		j.sex = '女';
		j.age = 18;
		System.out.println(j.name);
		System.out.println(j.sex);
		System.out.println(j.age);
		//操作子类属性
		j.yearNumber = "令和";
		System.out.println(j.yearNumber);
		//调用父类方法
		j.eat();
		j.sleep();
		//调用子类方法
		j.playVideo();
		
		}
	}
}

五、super关键字—父类

代表父类,作用于子类中:

​ super.属性/方法:调用父类非私有化的成员变量/方法

​ super():调用父类非私有化的构造方法

public class A {

	String str;
	
	public A() {
	}
	
	public void aMethod(){
		System.out.println("A类的方法");
	}
	
}

public class B extends A{
	
	public B() {
		//调用父类的非私有化构造方法
		super();
	}

	public void method(){
		
		//调用父类的非私有化属性
		super.str = "xxx";
		
		//调用父类的非私有化方法
		super.aMethod();
	}
}

六、方法重写

含义:重写也叫做复写,将父类中的方法在子类中重新编写一遍
应用场景:父类方法不满足子类需求时,子类就可以重复父类的方法
条件:
  1. 在子类中重写父类的方法
  2. 返回值、方法名和参数泪飙必须和父类重写的方法一致
  3. 访问修饰符不能比父类重写的方法更严,如父类为public 子类不能为private

七、访问修饰符

1.private 私有化的只允许本类访问

2.default 默认的只允许本类和本包的访问

3.protected 本类和本包以及其他包的子类可以访问

4.public 公共的 所有的均可以访问

八、Object类

含义: 基类也叫做超类,Object是所有类的祖先类

注意:如果一个类没有明确的继承父类,默认继承Object

1.equals()方法

比较两个对象的内存地址是否相同,Object不同的子类判断两个的对象是否相同有不同的判断规则,子类重写equals即可

public boolean equals(Object obj){
	return this==obj;
}
public class Test{
	public static void main(Stringp[] args){
		Object obj1=new Object();//0x001
		Object obj2=new Object();//0x002
		
		boolean equals=obj1.equalts(obj2)
		System.out.println(equalts);//false
		
		boolean bool==obj1==obj2;
		System.out.println(bool);//false
	}
}

2.hashCod()方法

获取对象的hash值

/**
hash值---系统利用对象的内存地址+散列算法获取的一个值
注意:hash值不等于内存值
*/
@Override
public int hashhCode(){
	return Object.hash(username,password);
}
public class User {
	
	private String username;
	private String password;

	public User() {
	}

	public User(String username, String password) {
		this.username = username;
		this.password = password;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
	
	@Override
	public boolean equals(Object obj) {
		if(this == obj){
			return true;
		}
		
		User user = (User) obj;
		if(this.username.equals(user.username)){
			return true;
		}
		return false;
	}
	
	@Override
	public String toString() {
		return username + " -- " + password;
	}
}

知识点:switch使用字符串细节
两个字符串hash值有可能相同

public class Test {

	public static void main(String[] args) {
		/**
		 * 知识点:switch使用字符串细节
		 * 
		 * 两个字符串hash值有可能相同
		 */

		String str = "ab";

		switch (str) {//switch (str.hashCode()) {
		case "ab"://case 3104:
			if(str.equals("ab")){
				System.out.println("ab");
			}
			break;
		case "aa"://case 3105:
			if(str.equals("aa")){
				System.out.println("aa");
			}
			break;
		case "bC"://case 3105:
			if(str.equals("bC")){
				System.out.println("bb");
			}
			break;
		}
	}
}

3.getClass()方法

获取类的字节码文件对象

public static void main(String[] args){
	Object obj1=new Object();
	Object obj2=new Object();
	Class<? extends Object> c1=obj1.getClass();
	Class<? extends Object> c2=obj2.getClass();
}

4.toString()方法

返回对象的字符串表示,Object不同的子类有不同的属性,重写toString,返回属性

//获取对象的字符表示(将对象转换为字符)
public String toString(){
	return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
public class Test{
	public static void main(String[] args) {
		
		
		User user1 = new User("1445584980", "123123");
		User user2 = new User("1445584980", "123123");
	
		System.out.println(user1.equals(user2));//true
	
		System.out.println(user1);//默认调用toString
	
	}
}

九、final关键字--------最终

1.final修饰的类

不能被继承

2.final修饰的方法

该方法不能被重写

3.final修饰的属性

变成常量不能重新赋值

十、抽象类和抽象方法

抽象方法交给非抽象的子类去实现(重写)

应用场景:

  1. 当一个方法必须在父类中出现,但是这个方法又不好实现,就把该方法,交给非抽象的子类去实现

  2. //抽象类
    public abstract class 类名{
        //抽象方法
        public abstract void method();
    }
    
  3. 面试题

    1. 抽象类不能有构造方法?抽象类可以有构造方法

    2. 抽象类中只能有抽象方法?抽象类中有非抽象方法(成员方法和静态方法)

    3. 抽象类中不可以没有抽象方法?抽象类中可以没有抽象方法,但是毫无意义

    4. 如果父类是抽象类,则子类必须实现父类的抽象方法?不一定,子类如果是抽象类,可以不实现父类的抽象方法

    5. 可以使用new关键字来创建抽象类对象?不可以,创建的是匿名内部类的对象

十一、接口

含义:特殊的抽象类

应用场景:接口更像一个规范

注意:

  1. JDK1.7时,接口中只能由静态常量和抽象方JDK
  2. JDK1.8开始,接口中有静态常量和抽象方法以及默认方法
  3. 接口是特殊的抽象类

作用:制定规范

//接口类
public interface I1{
    //默认添加public static final
    int i=100;//静态常量,不可以修改
    
    //默认添加abstract成为抽象类
    public void method01();
    public void method02();
    
    //默认方法
    default void defaultMethod(){
        System.out.println("接口中的默认方法");//JDK1.8版本开始
    }
    
    //静态方法
    public static void staticMethod(){
        System.out.println("接口中的静态方法");
    }
}
//实现接口类
public class A implements I1{
    @Override
    public void method01(){}
    
    @Override
    public void method02(){}
}
//测试类
public class Test{
    public static void main(String[] args){
        A a=new A();
        a.defaultMethod();
        I1.staticMethod();
    }
}
1.抽象类 VS 接口

抽象类:成员变量、静态变量、静态常量、成员方法、静态方法

接口:静态常量、静态方法、默认方法(JDK1.8)

  1. 相同之处:
    • 可编译成字节码文件
    • 不能创建对象
    • 可以作为引用类型
    • 具备Object类中所定义的方法
  2. 不同之处:
    • 所有属性都是公开静态常量,隐式使用public static final修饰
    • 所有方法都是公开抽象方法,隐式使用public abstract修饰
    • 没有构造方法、动态代码块、静态代码块
2.深入接口 面试题:
  1. 一个类可以实现多个接口?可以
  2. 一个接口可以实现多个接口?不可以,接口与接口的关系是多继承
  3. 接口里面的方法不一定都是抽象的?JDK1.7时接口里只能有抽象方法,JDK1.8时接口可以有抽象方法和默认方法
  4. 接口解决了类的单继承问题?是的,因为类与类是单继承,类与接口是多实现
  5. 一个类是否可以继承一个类并同时实现多个接口?可以
  6. 接口可以new对象?接口是特殊的抽象类,但是本质还是抽象类,抽象类是不可以new对象的,接口也是不能new对象,new出来的匿名类内部类的对象

代码实现上述面试题功能:

//接口1
public interface I1{
    public void i1Method01();
    public void method01();
    public void method02(){}
}
//接口2
public interface I2{
    public void i2Method01();
    public void method01();
    public void method02(){}
}
//接口3
public interface I3{
    public void i3Method01();
    public void method01();
}//接口4
public interface I4{
    public void i4Method01();
    public void method01();
}//接口5
public interface I5{
    public void i5Method01();
    public void method01();
}//接口6
public interface I6{
    public void i1Method01();
    public void method01();
}
//实现接口类
public class A extends Object implements I1,I2,I3{
    @Override
    public void i2Method01{}
    @Override
    public void i1Method01{}
    @Override
    public void i4Method01{}
    @Override
    public void i5Method01{}
    @Override
    public void i3Method01{}
    //I1、I2中都有method01的抽象方法,在实现类中只实现一个
    @Override
    public void method01(){}
    @Override
    public void method02(){
        //在实现类中调用I1接口中的默认方法
        //I1.super.method02();
        I2.super.method02();
    }
}
//测试类
public class Test{
    //1.创建匿名类,实现I5接口中的i5method01方法
    //2.创建匿名类的对象
    //3.赋值给接口的引用
    I5 i5=new I5(){
        @Override
        public void i5Method01(){};
    }
}
3.类与接口的关系:

类-----类:单继承

类-----接口:多实现

接口–接口:多继承

4.接口的好处:
  1. 程序的耦合度降低
  2. 更自然的使用多态
  3. 设计与实现完全分离
  4. 更容易搭建程序框架
  5. 更容易更换具体实现
5.接口总结
  1. 什么是接口
    • 从宏观上来看:接口是一种标准
    • 从微观上来看:接口是一种能力和约定
  2. 接口与类的异同
    • 没有构造方法,仅可定义公开静态常量与公开抽象方法
  3. 接口的应用
    • Java为单继承,当父类的方法种类无法满足子类需求时,可实现接口的扩充子类能力
  4. 接口的规范
    • 任何类在实现接口时,必须实现接口种所有的抽象方法,否则此类为抽象类
    • 实现接口种的抽象方法时,访问修饰符必须是public
  5. 什么是常量接口
    • 将多个常量用于表示状态或固定值的变量,以静态常量的形式定义在接口中题一管理
  6. 什么是接口回调?
    • 现有接口的使用者,后有接口的实现者

十二、多态

在面向对象中需要升级或者迭代时,进行修改数据,必须满足OCP原则,尽量不要改变以前的类,否则容易出现bug

OCP原则:

O—open:在需求升级或者迭代时,对于创建类是欢迎的

C----close:在需求升级或者迭代时,改变原有代码是拒绝的

P----principle:代表原则

1.类的多态

父类类名 引用=new 子类类名(); 引用.方法 —减少了代码的冗余,遵行了OCP原则

使用时,创建一个父类,用abstract抽象方法定义后,子类继承,测试类调用

//父类
public class Vehicle{
	public abstract void start();
	public abstract void stop();
}
//子类1
public class Bike{
    @Override
    public void start(){
        System.out.println("自行车:控制好龙头,蹬踏板")}
    @Override
    public void stop(){
        System.out.println("自行车:捏手刹,刹车");
    }
}
//子类2
public class Car{
    @Override
    public void start(){
        System.out.println("小汽车:点火,踩油门");
    }
    @Override
    public void stop(){
        System.out.println("小汽车:踩刹车和制动板,熄火停车");
    }
}
//子类3:
public class Plane{
    @Override
    public void start(){
        System.out.println("飞机:启动,当时速达到时,拉闸上飞");
    }
    @Override
    public void stop(){
        System.out.println("飞机:放下滑轮,减速,停机");
    }
}
//测试类
public class Test{
    public static void main(String[] args){
       
        Vehicle v=new Bike();
        Vehicle v1=new Car();
        Vehicle v2=new Plane();
        
        v.start();
        System.out.println("风景动人!!!!");
        v.stop();
        System.out.println("-------------");
        
        v1.start();
        System.out.println("风景动人!!!!");
        v1.stop();
        System.out.println("-------------");
        
        v2.start();
        System.out.println("风景动人!!!!");
        v2.stop();
        System.out.println("-------------");
    }
}
2.接口的多态

1

//测试类
public class Test{
    public static void main(String[] args){
        Computer computer=new Computer();
        //接口的多态:实现类的对象是指向接口的引用
        //接口的引用中存放的是实现类对象在堆中开辟空间的地址
        
        IUSB usb=new Keyboard();
        IUSB usb1=new Mouse();
        IUSB usb2=new Disk();
        
        computer.connection(usb);
        computer.connection(usb1);
        computer.connection(usb2);
    }
}
//连接usb的方法
public class Computer{
    public void connection(IUSB usb){
        usb.use();
    }
}
//接口
public interface IUSB{
    public void use();
}
//实现接口1
public class Disk implements IUSB{
    @Override
    public void use(){
        System.out.println("硬盘:上传下载文件");
    }
}
//实现接口2
public class Mouse implements IUSB{
    @Override 
    public void use(){
        System.out.println("鼠标:移动、左右点击");
    }
}
//实现接口3
public class Keyboard implements IUSB{
    @Override
    public void use(){
        System.our.println("键盘:输入数据");
    }
}

十三、对象转型

1.向上转型

子类类型 转 父类类型:

  1. ​ 可以调用父类非私有化属性
  2. ​ 可以调用父类非私有化方法
  3. ​ 可以调用子类重写父类的方法
  4. ​ 不可以调用子类属性和方法

注意:向上转型就是多态

**多态的缺点:**不可以调用子类自己的属性和方法

//测试类
public class Test{
    public static void main(String[] args){
        A a=new B();
        System.out.println(a.aAtrr);
        a.aMethod();
        a.method();
    }
}
//父类
public class A{
    String aAtrr="父类属性";
    public void aMethod(){
        System.out.println("父类方法");
    }
    public void method(){
        System.out.println("父类方法");
    }
}
//子类
public class B extends A{
    String bAtrr="子类属性";
    public void bMethod(){
        System.out.println("子类方法");
    }
    @Override
    public void mehthod(){
        System.out.println("子类重写父类方法");
    }
}
2.向下转型

父类类型 转 子类类型

//测试类
public class Test{
    public static void main(String[] args){
        Animal an=new Dog();//向上转型
        if(an instanceof Car){
            Car car=(Car) an;//向下转型
            car.shout();
        }else if(an instanceof Dog){
            Dog dog=(Dog) an;//向下转型
            dog.eat();
        }
        
    }
}
//父类
public class Animal{
    
}
//子类1
public class Car extends Animal{
    public void shout(){
        System.out.println("喵喵喵~~~~");
    }
} 
//子类2
public class Dog extends Animal{
    public void eat(){
        System.out.println("吃骨头!");
    }
}

注意:

  1. 向下转型转不好就会出现ClassCasteException—类型转换异常

  2. 向下转型一定要使用instanceof判断

    //类
    public class MyString{
        private String value;
        public MyString(String value){
            this.value=value;
        }
        @Override
        public boolean equalts(Object obj){
            if(this==obj){
                return true;
            }
            if(obj instanceof MyString){
                Mystring m=(MyString) obj;
                //['a','b','c']
                char[] v1=this.value.toCharArray();//把当前对象的str转换为字符组
                //['a','b','c']
                char[] v2=m.value.toCharArray();//把当前对象的str转换为字符数组
                if(v1.length!=v2.length){
                    return false;
                }
                for(int i=0;i<v2.length;i++){
                    if(v1[i]!=v2[i]){
                        return false;
                    }
                }
                return true;
            }
            return false;
        }
        @Override
        public String toString(){
            return value;
        }
    }
    //测试类
    public class Test{
        public static void main(String[] args){
            String str1 = new String("abc");
    		String str2 = new String("abc");
    		System.out.println(str1 == str2);//false
    		System.out.println(str1.equals(str2));//true - 比较两个字符串内容是否相同
    		System.out.println(str1);//默认调用toString
    		System.out.println(str2);//默认调用toString
    		
    		System.out.println("--------------");
    		
    		MyString m1 = new MyString("abc");
    		MyString m2 = new MyString("abc");
    		System.out.println(m1 == m2);//false
    		System.out.println(m1.equals(m2));
    		System.out.println(m1);
    		System.out.println(m2);
        }
    }
    

十四、内部类

应用场景:

内部类的应用场景:

  1. 如果一个类的对象只在另外一个类中使用。就可以考虑把该类变成成员内部类或者静态内部类。

    如果内部类要用到外部类的所有属性就把该类变成成员内部类

    如果内部类只用到外部类的静态类就把该类变成静态内部类

  2. 如果一个类的对象只在另外一个类的方法中使用,就可以把该类变成局部内部类,一般不适用这种设计思想

  3. 如果一个类的对象只在接口中使用,就可以考虑把该类变成接口内部类,一般不适用这种设计思想

  4. 抽象类子类的对象或者是接口实现类对象只使用到一次,就可以考虑使用匿名内部类

1.成员内部类

特点:可以调用外部类中的所有属性

//外部类
public class Outter{
    private   String str="aaa";
    default   String str1="bbb";
    protected String str2="ccc";
    public	  String str3="ddd";
    final	  String str4="eee";
    static 	  String str5="fff";
	
    //成员内部类
    class Inner{
        private String str1="成员内部里的属性";
        public void method{
            System.out.println("成员内部类里的方法");
            System.out.println(this.str);
            System.out.println(Outter.this.str);//调用外部类属性
            System.out.println(str1);//Outter.this.str1
            System.out.println(str2);//Outter.this.str2
            System.out.println(str3);//Outter.this.str3
            System.out.println(str4);//Outter.this.str4
            System.out.println(str5);//Outter.this.str5
        }
    }
}
//测试类
public class Test{
    public static void main(String[] args){
        //创建成员内部类对象
        Outter.Inner inner=new Outter().new Inner();
        
        //调用方法
        inner.method();
    }
}
2.静态内部类

特点:只能调用外部类的静态属性

//外部类
public class Outter{
    private   String str="aaa";
    default   String str1="bbb";
    protected String str2="ccc";
    public	  String str3="ddd";
    final	  String str4="eee";
    static 	  String str5="fff";
	
    //静态内部类
    static class Inner{
        public void method{
            System.out.println("静态内部类里的方法");
            System.out.println(str5);//Outter.this.str5
        }
    }
}
//测试类
public class Test{
    public static void main(String[] args){
        //创建静态内部类对象(不用创建外部类对象)
        Outter.Inner inner=new Outter.Inner();
        
        //调用方法
        inner.method();
    }
}
3.接口内部类

注意:接口内部类底层就是静态内部类

/外部类
public class Outter{
	//接口内部类默认添加public static
    class Inner{
        public void method{
            System.out.println("接口内部类里的方法");
        }
    }
}
//测试类
public class Test{
    public static void main(String[] args){
        //创建接口内部类对象
        Outter.Inner inner=new Outter.Inner();
        
        //调用方法
        inner.method();
    }
}
4.局部内部类
/外部类
public class Outter{
    public void function{
	//局部内部类
    	class Inner{
       		public void method{
            	System.out.println("局部内部类里的方法");
        	}
    	}
    //创建局部内部类的对象
    Inner inner=new Inner();
    //调用方法
    inner.method();
    }
}
//测试类
public class Test{
    public static void main(String[] args){
        //创建外部类对象
        Outter.Inner outter=new Outter();
        
        //调用方法
        outter.function();
    }
}

在局部内中使用到变量时,JDK1.8版本开始自动变成常量

即默认添加了public static final

//测试类
public class Test{
    public static void main(String[] args){
        //创建外部类的对象
        Outter outter=new Outter();
        
        //调用方法
        Object obj=outter.function();
        System.out.println(obj);
    }
}
//外部类
public class Outter{
    public Object function(){
        /**
        如果局部内部类中使用到该变量,JDK1.8开始变量自动编程常量
        因为防止i在该方法结束后才会使用
        由于当function()方法在栈中使用结束后,function()方法被销毁后,但是需要在main中将obj进行调用i时;当i为变量时,在function()方法中直接被销毁了,无法调用。故只能默认添加final将i变成常量,从而i在堆中的常量池中,只有程序结束以后,常量池才能被销毁,以此来保证i的存活时间更久,避免bug。
        */
        int i=100;//默认添加final
        //局部内部类
        class Inner{
            @Override
            public String toString{
                return i+"";
                
            }
        }
        //创建局部内部类的对象
        Inner inner=new Inner();
        return inner;
    }
}
5.匿名内部类
//抽象类
public abstract class A{
    public abstract void method();
}
//接口类
public interface I1{
    public void method();
}
//测试类
public class Test01{
    public static void main(String[] args){
        //1.创建匿名子类,继承A,重写method
		//2.创建匿名子类对象,赋值给父类的引用
        A a=new A(){
            @Override
            public void method(){}
        };
    }
}
//测试类2
public class Test02{
    public static void main(String[]args){
        //1.创建匿名实现类,实现I1中的method
		//2.创建匿名实现类的对象,指向接口的引用
        I1 i1=new I1(){
            @Override
            public void method(){}
        };
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

榮十一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值