• Java之面向对象


    JavaSE

    面向对象

    • 文件名
      • 在一个java文件写两个类:一个基本类,一个测试类
    • 对象
      • 类名 对象名 = new 类名( );
    • 使用成员变量
      • 对象名.变量名
    • 使用成员方法
      • 对象名.方法名(...)
    class Demo1_student{
    	public static void main(String [] args) {
    		Student s = new Student();
            /*
    		 * 1. 声明一个引用变量(栈),栈中开辟s
    		 * 2. 通过new关键字 在 堆中开辟 存储 Student对象
    		 * 3. 通过赋值将堆Student地址传给栈中的s
    		 * */
    		s.name = "Mephisto";
    		s.age = 14;
    		s.gender = "Male";
    		s.study();
    		s.sleep();
    		System.out.println("学生姓名:" + s.name + "   "+  "学生性别: "+ s.gender);		
    				
    	}
    }
    
    class Student {
    	String name;
    	int age;
    	String gender;
    	public void study() {
    	
    		System.out.println("学生学习");
    		
    	}
    	public void sleep() {
    		System.out.println("学生睡觉");
    	}
    }
    

    成员变量和局部变量区别:

    • 在类中的位置不同:

      • 成员变量:在类中方法外
      • 局部变量:在方法定义中或方法声明上
    • 在内存中的位置不同:

      • 成员变量: 在堆内存(成员变量属于对象, 对象进 堆内存)
      • 局部变量: 在栈内存(局部变量属于方法, 方法进 栈内存)
    • 生命周期不同

      • 成员变量: 随着对象的创建而存在,随着对象的消失而消失
      • 局部变量: 随着方法的调用而存在,随着方法的调用完毕而消失
    • 初始化值不同

      • 成员变量有默认的初始化值
      • 局部变量没有默认的初始化值, 必须定义,赋值,然后才能使用
    • 注意事项

      • 局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的就是就近原则
      • 基本数据类型变量包括 byte, short, int , long, float, double, boolean, char
      • 引用数据类型变量包括 数组 类 接口 枚举

    面向对象(如何调用对象方法的形式参数是类名)

    public class Demo3 {
    	public static void main(String [] args) {
    		print(10);
    		Demo_Student s = new Demo_Student(); //创建对象,并将对象的地址值赋值给s
    		print(s);	
    	}
    	public static void print(int x) {	// 基本数据类型当作形式参数
    		System.out.println(x);
    	}	
    	public static void print(Demo_Student s) {	// 引用数据类型当作形式参数
    		s.name = "Mephisto";
    		s.age = 22;
    		s.speak();
    	}
    	
    }
    
    /*
     * 方法的参数名是类名  public void print(Demo_Student s){}  // print(new Student));
     *  一个方法的形式参数是一个类类型(引用数据类型), 需要的是该类的对象;
     * */
    
    
    
    
    class Demo_Student{
    	String name;
    	int age;
    	public void speak() {
    		System.out.println(name + "    " + age);
    	}
    }
    

    面向对象(匿名对象)

    /*
     * 匿名对象: 没有名字的对象
     * 匿名对象应用场景: 调用方法, 仅仅调用一次的时候 , 匿名调用节省代码
     * 调用多次的时候不合适, 匿名对象调用完毕就是垃圾, 可以被垃圾回收器回收
     * 匿名对象可以作为实际参数传递
     */
    public class Demo4 {
    	
    	public static void main(String [] args) {
    		/*
    		Car c1 = new Car(); // 创建有名字的对象
    		c1.run();
    		
    		
    		new Car().run();	// 匿名对象调用方法  , 对方法的一次调用 每次调用产生多个对象
    		*/
    		
    		// 匿名对象是否可以调用属性并赋值? 有什么意义
    		
    		/*
    		 * 匿名对象可以调用属性,但是没有意义, 因为调用之后就变成了垃圾
    		 * 如果调用还是用有名字的对象
    		
    		
    			new Car().color = "red";
    			new Car().run();
    		 
    		 */
    		
    		/*
    		Car c1 = new Car();
    		c1.color = "red";
    		c1.run();
    		
    		
    		Car c2 = new Car();
    		c2.color = "yellow";
    		c2.run();
    		*/
    		
    		/*
    		Car c1 = new Car();
    		method(c1);
    		
    		Car c2 = new Car();
    		method(c2);
    		
    		*/
    		
    		
    		// 匿名对象可以作为实际参数传递
    		method(new Car());
    		method(new Car());
    		
    		
    	}
    	
    	// 抽取方法提高代码复用性
    	public static void method(Car cc) {
    		cc.color = "red";
    		cc.run();
    	}
    
    }
    class Car{
    	String color;
    	
    	public void run() {
    		
    		System.out.println(color + "车运行起来了");
    		
    	}
    }
    
    
    
    

    面向对象(封装)

    • 封装概述
      • 是指隐藏对象的属性和实现细节, 仅对外公开访问方式
    • 封装好处
      • 隐藏实现细节, 提供公共的访问方式
      • 提高了代码的复用性
      • 提高安全性
    • 封装原则
      • 将不需要对外提供的内容都隐藏起来
      • 把属性隐藏提供公共方法对其访问
    • private关键字特点
      • 是一个权限修饰符
      • 可以修饰成员变量和成员方法
      • 被其修饰的成员只能在本类中被访问
    package learn_javaSe;
    /*
     * 封装和private的应用:
     * 把成员变量用private修饰
     * 提供对应的getXXX()和setXXX()方法
     * private仅仅是封装的一种形式体现, 不能说封装就是私有
     */
    public class Demo5 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Demo5_Person p1 = new Demo5_Person();
    		p1.name = "Mephisto";
    		/*
    		p1.age = -22;
    		p1.speak();
    		*/
    		
    		p1.setAge(-22);
    		System.out.println(p1.getAge());
    	}
    
    }
    
    class Demo5_Person{
    	String name;	// 姓名
    	private int age;		// 年龄
    	
    	public void setAge(int a) {	// 设置年龄
    		if( a> 0 && a < 200)
    			age = a;
    		else	
    			System.out.println("请输入正常的年龄");
    	}
    	public int getAge() {		// 获取年龄
    		return age;
    	}
    	
    	public void speak() {
    		System.out.println(name + "   " + age);
    	}
    }
    

    面向对象(this关键字)

    
    
    /*
     * this关键字特点: 代表当前对象的引用
     * 区分成员变量和局部变量
     */
    
    
    
    public class Demo6 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Demo6_person p = new Demo6_person();
    		p.setName("Mephisto");
    		p.setAge(15);
    		System.out.println(p.getName() + "  " + p.getAge());
    		
    		
    		Demo6_person p2 = new Demo6_person();
    		p2.setName("Vincent");
    		p2.setAge(25);
    		System.out.println(p2.getName() + "  " + p2.getAge());
    
    	}
    
    }
    class Demo6_person{
    	
    		private String name;	// 姓名
    		private int age;		// 年龄
    		
    		public void setName(String name) {
    			this.name = name;
    		}
    		public String getName() {
    			return name;
    		}
    		
    		
    		public void setAge(int age) {	// 设置年龄
    			if( age> 0 && age < 200)
    				this.age = age;
    			else	
    				System.out.println("请输入正常的年龄");
    		}
    		public int getAge() {		// 获取年龄
    			return age;
    		}
    }
    
    手机类
    package learn_javaSe;
    
    public class Demo7 {
    
    	public static void main(String[] args) {
    		Demo7_Phone p =new Demo7_Phone();
    		p.setBrand("魅族");
    		p.setPrice(2499);
    		System.out.println(p.getBrand() + "  " + p.getPrice());
    		p.call();
    		p.playGame();
    		p.sendMessage();
    	}
    }
    
    /*
     * 手机类:
     * 属性: 品牌brand 价格 price
     * 行为: 打电话call, 发信息 sendMessage 玩游戏 playGame
     */
    
    
    class Demo7_Phone{			// java bean 
    	private String brand; // 品牌
    	private int price;	//价格
    	
    	public void setBrand(String brand) {		// 设置品牌
    		this.brand = brand;
    	}
    	public String getBrand() {		//获取品牌
    		return this.brand;		// this.可以省略, 系统默认加上
    	}
    	public void setPrice(int price) {	// 设置价格
    		this.price = price;
    	}	
    	public int getPrice() { 		// 获取价格
    		return price;
    	}
    	
    	public void call() {
    		System.out.println("打电话");
    		
    	}
    	public void sendMessage() {
    		System.out.println("发短信");
    	}
    	public void playGame() {
    		System.out.println("玩游戏");
    	}
    	
    	
    }
    

    构造方法

    构造方法: 给对象的数据(属性) 进行初始化

    构造方法格式和特点:

    ​ 方法名与类名相同(大小也和类名一致)

    ​ 没有返回值类型, 连void也没有

    ​ 没有具体的返回值 return;

    package learn_javaSe;
    
    public class Demo8 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Demo8_Person p = new Demo8_Person();		// 在创建对象的时候就已经调用了构造方法
    		//		p.Demo8_Person  // 构造方法不能通过对象调用
    		p.show();
    	}
    
    }
    class Demo8_Person{
    	private String name;
    	private int age;
    	// 构造方法
    	public Demo8_Person(){
    //		System.out.println("Hello world!");
    //		return;		// 构造方法也是有return语句的   格式: return;
    		name = "Mephisto";
    		age = 10;
    		return;
    	}
    	public void show() {
    		System.out.println(name + "  " + age);
    	}
    	
    }
    
    

    面向对象(构造方法的重载及注意事项)

    • 构造方法的重载:方法名相同,与返回值类型无关(构造方法没有返回值),只看参数列表
    • 注意事项
      • 如果没有给出构造方法, 系统将默认提供一个无参构造方法
      • 如果给出了构造方法,系统将不再提供默认的无参构造方法
        • 还想使用无参构造方法,需要自己给出
    public class Demo9 {
    	public static void main(String [] args) {
    		Demo9_Person p1 = new Demo9_Person();
    		p1.show();
    		System.out.println("----------------------");
    		
    		Demo9_Person p2 = new Demo9_Person("Mephisto",18);
    		p2.show();
    		
    		Demo9_Person p3 = new Demo9_Person("Vincent",17);
    		p3.show();
    		
    	}
    }
    
    class Demo9_Person{
    	private String name;
    	private int age;
    	
    	public Demo9_Person() {
    		System.out.println("空参的构造参数");
    	}
    	
    	public Demo9_Person(String name,int age) {
    		this.name = name;
    		this.age = age;
    		
    		System.out.println("有参的构造方法");
    	}
    	
    	
    	public void show() {
    		System.out.println(name + "  " + age);
    	}
    	
    }
    

    构造方法和setXXX()方法区别

    public class Demo10 {
    
    	public static void main(String[] args) {
    		Demo10_Person p1 = new Demo10_Person("Mephisto",18);
    		// p1 = new Demo10_Person("李四",19);  // 重新创建的新对象,不是对原对象的修改,将原对象变成垃圾
    		System.out.println(p1.getName()+"   "+ p1.getAge());
    		System.out.println("============================");
    		
    		Demo10_Person p2= new Demo10_Person();
    		p2.setName("Vincent");
    		p2.setAge(24);
    		
    		p2.setName("张三");
    		System.out.println(p2.getName()+"   "+ p2.getAge());
    	}
    
    }
    /*
     * 构造方法  给属性进行初始化
     * setXXX()方法  修改属性值, 更加灵活
     */
    class Demo10_Person{
    	private String name;
    	
    	private int age;
    	
    	public Demo10_Person() {
    		
    	}
    	public Demo10_Person(String name, int age) {
    		this.name = name;
    		this.age = age;
    	}
    	
    	public void setName(String name) {
    		this.name = name;
    	}
    	public String getName() {
    		return name;
    	}
    	
    	
    	public void setAge(int age) {
    		this.age = age;
    	}
    	public int getAge() {
    		return age;
    	}
    	
    }
    
    Student s = new Student();
    
    • Student.class加载进内存
    • 声明一个Student类型引用
    • 在堆内存创建对象
    • 给对象中属性默认初始化值
    • 属性进行显示初始化
    • 构造方法进栈, 对对象中的属性赋值, 构造方法弹栈
    • 将对象的地址值赋值给s

    static

    static关键字的特点:

    • 随着类的加载而加载
    • 优先于对象的存在
    • 被类的所有对象共享(例如班级号被全班同学共享)
    • 可以通过类名调用
    • 本身可以通过对象名调用
    • 推荐使用类名调用
    • 静态修饰的内容一般我们称其为: 与类相关的, 类成员
    public class Demo16 {
    
    	public static void main(String[] args) {
    		/*
    		Demo16_Person p1 = new Demo16_Person();
    		p1.name = "mephisto";
    		p1.country = "中国";
    		
    		
    		
    		Demo16_Person p2 = new Demo16_Person();
    		p2.name = "Vincent";
    		
    		
    		p1.speak();
    		p2.speak();
    		*/
    		Demo16_Person.country = "中国";
    		System.out.println(Demo16_Person.country);
    
    	}
    
    }
    
    class Demo16_Person{
    	String name;
    	static String country; // 静态
    	
    	public void speak() {
    		System.out.println(name + "  " + country);
    	}
    	
    }
    

    static注意事项

    package learn_javaSe;
    
    public class Demo17 {
    
    	public static void main(String[] args) {
    		Demo17_Test demo = new Demo17_Test();
    		demo.print1();
    
    	}
    
    }
    /* static的注意事项
     * 在静态方法中是没有this关键字的
     * 静态是随着类的加载而加载,this是随着对象的创建而存在的
     * 静态比对象现存在
     * 静态方法只能访问静态的成员变量和静态的成员方法
     * 静态方法: 
     * 		成员变量: 只能访问静态变量
     * 		成员方法: 只能访问静态成员方法
     * 
     * 非静态方法: 
     * 		成员变量: 可以是静态的, 也可以是非静态的
     * 		成员方法: 可以是静态的成员方法, 也可以是非静态的成员方法
     * 
     * 静态只能访问静态, 静态先于非静态存在
     * 
     */
    
    class Demo17_Test{
    	int num1 = 10; 	// 非静态成员变量
    	static int num2 = 20; 	// 静态成员变量
    	
    	public void print1() {	// 非静态的成员方法, 可以访问静态的成员变量也可以访问非静态的成员变量
    		System.out.println(num1);
    		System.out.println(num2);
    	}
    	
    	
    	public static void print2() {	// 静态成员方法
    		// System.out.println(num1);	// 静态方法无法访问非静态成员变量
    		System.out.println(num2);
    	}
    	
    }
    

    静态变量和成员变量的区别

    静态变量也叫类变量, 成员变量也叫对象变量

    • 所属不同
      • 静态变量属于类, 所以也成为类变量
      • 成员变量属于对象, 所以也成为实例变量( 对象变量 )
    • 内存中位置不同
      • 成员变量存储于方法区中的静态区
      • 成员变量存储于堆内存中
    • 内存出项的时间不同
      • 静态变量随着类的加载而加载, 随着类的消失而消失
      • 成员变量随着对象的创建而存在, 随着对象的消失而消失
    • 调用不同
      • 静态变量可以通过类名调用, 也可以同通过对象调用
      • 成员变量只能通过对象名调用
    package learn_javaSe;
    
    
    
    public class Demo18 {
    	public static void main(String [] args) {
    		Test18 t1 = new Test18();
    		t1.print1();
    		String t2 = Test18.name2.toString(); // 静态 变量可以通过类名调用
    		System.out.println(t2);
    	}
    }
    
    
    class Test18{
    	String name1 = "Mephisto";
    	static String name2 = "Vincent";
    	
    	public void print1() {
    		System.out.println(name1);
    	}
    	
    	public void print2() {
    		System.out.println(name2);
    	}
    	
    }
    

    main方法的格式解释

    package learn_javaSe;
    
    public class Demo19 {
    	public static void main(String [] args) {
    		
    		/*
    		 * public : 被jvm调用, 所以权限要足够大
    		 * static : 被jvm调用, 不需要创建对象名, 直接类名, 调用即可
    		 * main   : 只有这样写才能被jvm识别, main不是关键字
    		 * String [] args : 以前是用来接受键盘录入的
    		 * 
    		 */
    		
    		System.out.println(args.length);
    		for(int i = 0; i < args.length; i++) {
    			System.out.println(args[i]);
    		}
    	}
    
    }
    

    如果一个类中所有方法都是静态的, 需要私有构造方法, 私有构造方法之后其他类无法创建该类的对象

    文档注释(说明书)

    @author 提取作者内容

    @version 提取版本内容

    @param 参数名称

    @return 函数运行完返回的数据

    javadoc -d 保存文件 -version -author XXXX.java
    

    代码块

    在java中, 使用{ }括起来的代码被称为代码块

    代码块分类:
    • 局部代码块 在方法中出现, 限定变量生命周期, 及早释放提高内存利用率
    • 构造代码块 在类方法外出现, 多个构造方法中相同的代码放在一起, 每次调用构造都执行,并且在构造方法前执行
    • 静态代码块
      • 在类中方法外出现, 加了static修饰
      • 在类中方法外出现, 并加上了static修饰,用于给了类进行初始化, 在加载的时候就执行, 并且只执行一次
      • 一般用于加载驱动
    • 同步代码块
    package learn_javaSe;
    
    public class Demo23 {
    
    	public static void main(String[] args) {
    //		{
    //			int x = 10; // 限制变量的生命周期
    //			System.out.println(x);
    //		}
    		
    		Test23 stu1 = new Test23();
    		System.out.println("---------------");
    		Test23 stu2 = new Test23("Mephisto",22);
    		System.out.println("---------------");
    	}
    	
    	static {
    		System.out.println("主方法类中的静态代码块");   // 优先于主方法执行
    	}
    }
    class Test23{
    	private String name;
    	private int age;
    	
    	public Test23() {
    		// study();
    		System.out.println("空参构造");
    	}
    	public Test23(String name, int age) {
    		// study();
    		this.name = name;
    		this.age = age;
    		System.out.println("有参构造");
    	}
    	
    	public void setName(String name) {
    		this.name = name;
    	}
    	public String getName(){
    		return name;
    		}
    	public void setAge(int age) {
    		this.age = age;
    	}
    	public int getAge() {
    		return age;
    	}
    	{
    		// System.out.println("构造代码块");
    		study();
    	}
    	
    	public void study() {
    		System.out.println("学习");
    	}
    	static {
    		System.out.println("静态代码块");	// 随着类的加载而加载, 且执行一次, 作用: 给类进行初始化, 一般用来加载驱动
    	}
    }
    
    
    输出结果
    主方法类中的静态代码块
    静态代码块
    学习
    空参构造
    ---------------
    学习
    有参构造
    ---------------
    
    package learn_javaSe;
    
    public class Demo24 {
    	static {
    		System.out.println("Demo24 静态代码块");
    	}
    	public static void main(String[] args) {
    		System.out.println("main方法");
    		
    		Test24 t1 = new Test24();
    		Test24 t2 = new Test24();
    
    	}
    
    }
    
    
    class Test24{
    	
    	static {
    		System.out.println("Test24  静态代码块");
    		
    	}
    	{
    		System.out.println("Test24  构造代码块");
    	}
    	public Test24() {
    		System.out.println("Test24  构造方法");
    	}
    	
    }
    
    
    输出结果
    Demo24 静态代码块
    main方法
    Test24  静态代码块
    Test24  构造代码块
    Test24  构造方法
    Test24  构造代码块
    Test24  构造方法
    

    继承(extends)

    让类和类之间产生关系, 父子关系

    package learn_javaSe;
    
    public class Demo25 {
    
    	public static void main(String[] args) {
    		Cat c1 = new Cat();
    		c1.color = "red";
    		c1.leg = 4;
    		c1.eat();
    		c1.sleep();
    		c1.show();
    	}
    
    }
    
    class Animal{
    	String color;
    	int leg;
    	
    	
    	public void eat() {
    		System.out.println("吃饭");
    	}
    	public void sleep() {
    		System.out.println("睡觉");
    	}
    	
    	
    	public void show() {
    		System.out.println(color + " " + leg + " ");
    	}
    }
    
    class Cat extends Animal{
    	
    
    }
    
    class Dog extends Animal{
    
    }
    
    
    • 继承的好处

      • 提高代码的复用性
      • 提高代码的维护性
      • 让类与类之间产生了关系, 是多态的前提
    • 继承的弊端

      • 类的耦合性增强了
      • 开发的原则: 高内聚, 低耦合
      • 耦合: 类与类之间的关系
      • 内聚: 就是自己完成某件事情的能力
    • Java中类的继承特点:

      • Java只支持单继承, 不支持多继承 , 多继承有安全隐患

        • 有些语言支持多继承, 格式: extends 类1, 类2 .....
      • Java支持多层继承(继承体系)

        • 使用这个体系使用最底层
        • 想看共性看最顶层
    package learn_javaSe;
    
    public class Demo26 {
    	public static void main(String [] args) {
    		DemoC d = new DemoC();
    		d.print();
    		d.show();
    		d.method();
    	}
    }
    
    
    class DemoA{
    	public void show() {
    		System.out.println("DemoA");
    	}
    }
    class DemoB extends DemoA{
    	public void method() {
    		System.out.println("DemoB");
    	}
    }
    class DemoC extends DemoB{
    	public void print() {
    		System.out.println("DemoC");
    	}
    }
    
    输出结果
    DemoC
    DemoA
    DemoB
    

    继承的注意事项

    子类只能继承父类所有非私有的成员(成员方法和成员变量)

    子类不能继承父类的构造方法, 但是可以通过super()关键字去访问父类构造方法

    不要为了部分功能而去继承

    package learn_javaSe;
    
    public class Demo27 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Son s = new Son();
    		s.print();
    
    	}
    
    }
    
    /*
     * a: 不同名变量
     * b: 同名变量 
     * 在开发中是不出现子父类同名变量
     * 子类继承父类就是为了使用父类成员, 如果定义了同名的成员变量就没有意义了
     */
    
    
    
    class Father{
    	int num1 = 10;
    	int num2 = 30;
    }
    
    class Son extends Father{
    	int num2 = 20; 
    	public void print() {
    		System.out.println(num1);	// 10 
    		System.out.println(num2);	// 20   就近原则, 子类有 不用父类
    	}
    }
    
    输出结果
    10
    20
    

    this和super的区别

    • this和super都代表什么

      • this, 代表当前对象的引用, 谁来调用我, 我就代表谁
      • super: 表示当前对象父类的引用
    • this和super的使用区别:

      • 调用成员变量:
        • this, 成员变量调用的是本类的成员变量, 也可以调用父类的成员变量
        • super, 成员变量调用父类的成员变量
      • 调用构造方法
        • this(...) 调用本类的构造方法
        • super(...) 调用父类的构造方法
      • 调用成员方法
        • this.成员方法 调用本类的成员方法, 也可以调用父类的成员方法
        • super.成员方法 调用父类的成员方法
      package learn_javaSe;
      
      public class Demo28 {
      
      	public static void main(String[] args) {
      		// TODO Auto-generated method stub
      		Demo28_Son s1 = new Demo28_Son();
      		s1.print();
      	}
      
      }
      
      class Demo28_Father{
      	
      	int num1 = 10;
      	int num2 = 20;
      	
      	
      }
      class Demo28_Son extends Demo28_Father{
      	int num2 = 30;
      	public void print() {
      		System.out.println(num1);
      		System.out.println(num2);
      		System.out.println(super.num2);
      	}
      }
      
      输出结果
      10
      30
      20
      
    • 子类中多有的构造方法默认都会访问父类中空参构造方法

      • 因为子类会继承成父类中的数据, 可能还会使用父类的数据
      • 所以, 子类初始化之前, 一定要完成父类数据的初始化
    • 每个构造方法的第一句默认都是: super() Object类最顶端的父类

    package learn_javaSe;
    
    public class Demo29 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Demo29_Son s1 = new Demo29_Son();
    		
    	}
    }
    class Demo29_Father{
    	public Demo29_Father() {
    		super();  // 默认添加super()     访问Object类, Object是最顶层的类
    		System.out.println("Father 的构造方法!");
    	}
    }
    class Demo29_Son extends Demo29_Father{
    	public Demo29_Son() {
    		super();   // 系统默认添加 super(),  用来访问父类中的空参构造
    		
    		System.out.println("Son的构造方法!");
    	}
    	
    }
    
    输出结果
    Father 的构造方法!
    Son的构造方法!
    
    • 父类中没有无参构造怎么办
    package learn_javaSe;
    
    public class Demo30 {
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Demo30_Son s1 = new Demo30_Son();
    		System.out.println(s1.getName() + "   " + s1.getAge());
    		System.out.println("----------------------");
    		Demo30_Son s2 = new Demo30_Son("Mephisto",25);
    		System.out.println(s2.getName() + "   " + s2.getAge());
    	}
    
    }
    class Demo30_Father{
    	private String name;
    	private int age;
    	/*
    	public Demo30_Father() {
    		// super();
    		System.out.println("Father空参构造");
    	}
    	*/
    	public Demo30_Father(String name, int age) {
    		// super();
    		this.name = name;
    		this.age = age;
    		System.out.println("Father有参构造");
    	}
    	
    	public void setName(String name) {
    		this.name = name;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setAge(int age) {
    		this.age = age;
    	}
    	public int getAge() {
    		return age;
    	}
    	
    }
    
    class Demo30_Son extends Demo30_Father{
    
    	public Demo30_Son() {
    //		super("Vincent",18);  // 调用父类中的构造方法
    		this("Vincent",18);		// 调用本类中的构造方法, 即访问 public Demo30_Son(String name, int age){}
    		System.out.println("Son空参构造");
    	}
    
    	public Demo30_Son(String name, int age) {
    		super(name,age);
    		System.out.println("Son有参构造");
    	}
    }
    
    输出结果
    Father有参构造
    Son有参构造
    Son空参构造
    Vincent   18
    ----------------------
    Father有参构造
    Son有参构造
    Mephisto   25
    
    package learn_javaSe;
    
    public class Demo31 {
    
    	public static void main(String[] args) {
    		Zi zi = new Zi();
    		zi.show();
    
    	}
    
    }
    class Fu{
    	public int num = 10;
    	
    	public Fu() {
    		System.out.println("Fu");
    	}
    }
    
    class Zi extends Fu{
    	public int num = 20;
    	
    	public Zi() {
    		System.out.println("Zi");
    	}
    	
    	public void show() {
    		int num = 30;
    		System.out.println(num);
    		System.out.println(this.num);
    		System.out.println(super.num);
    	}
    }
    
    输出结果
    Fu
    Zi
    30
    20
    10
    
    package learn_javaSe;
    
    public class Demo32 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Demo32_Zi zi = new Demo32_Zi();
    	}
    	
    	/*
    	 * 1. JVM 调用了main方法, main进栈
    	 * 2. 遇到 Demo32_Zi zi = new Demo32_Zi(); 会先将Demo32_Fu 和 Demo32_Zi加载进内存, 在创建对象
    	 * 	     同时父类和子类的静态代码块也会加载进内存  第一个输出时 Fu静态代码块, 第二个输出   Zi静态代码块
    	 * 3. 走Demo32_Zi类的构造方法, 因为java中是分层初是化的, 先初始化父类, 然后在初始化父类, 
    	 * 	     所以先走父类的构造,但是在执行父类构造时, 发现父类构造代码块, 构造代码块是优先于构造方法执行的
    	 * 	     所以第三个输出  Fu构造代码块  第四个输出  Fu构造方法
    	 * 4. Demo32_Fu类加载完毕, 加载Demo32_Zi 第五个输出  Zi构造代码块 , 第六个输出  Zi构造方法
    	 */
    	
    	
    	
    	
    }
    
    
    class Demo32_Fu{
    	static {
    		System.out.println("Fu静态代码块");
    	}
    	{
    		System.out.println("Fu构造代码块");
    	}
    	public Demo32_Fu() {
    		System.out.println("Fu构造方法");
    	}
    }
    class Demo32_Zi extends Demo32_Fu{
    	static {
    		System.out.println("Zi静态代码块");
    	}
    	{
    		System.out.println("Zi构造代码块");
    	}
    	public Demo32_Zi() {
    		System.out.println("Zi构造方法");
    	}
    }
    
    
    输出结果
    Fu静态代码块
    Zi静态代码块
    Fu构造代码块
    Fu构造方法
    Zi构造代码块
    Zi构造方法
    
    package learn_javaSe;
    
    public class Demo33 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Demo33_Zi z1 = new Demo33_Zi();
    		z1.print();
    		z1.method();
    	}
    
    }
    
    /*
     * 不同名方法
     * 同名方法 
     */
    
    
    class Demo33_Fu{
    	public void print() {
    		System.out.println("Fu print");
    	}
    }
    class Demo33_Zi extends Demo33_Fu{
    	public void method() {
    		System.out.println("Zi method");
    	}
    	
    	
    	public void print() { //  重写 
    		super.print();	// super可以调用父类的成员方法
    		System.out.println("Zi print");
    	}
    }
    
    输出结果
    Fu print
    Zi print
    Zi method
    

    方法重写

    重写: 子父类出现了一模一样的方法(返回值可以时子父类)

    当子类需要父类一个功能,而功能主体子类有自己特有的内容时,可以重写父类中的方法, 这样, 即沿袭了父类的功能, 有定义了子类特有的内容

    package learn_javaSe;
    
    public class Demo34 {
    	public static void main(String[] args) {
    		NewPhone p1 = new  NewPhone();
    		p1.siri();
    		p1.call();
    		p1.show();
    	}
    
    }
    
    class Demo34_Phone{
    	public void call() {
    		System.out.println("打电话!");
    	}
    	public void siri() {
    		System.out.println("Speak English!");
    	}
    	public static void show(){
    		System.out.println("Fu static show");
    	}
    }
    
    class NewPhone extends Demo34_Phone{
    	
    	public void siri() {
    		super.siri();
    		System.out.println("说中文");
    	}
    	
    	public static void show() {  // 静态只能覆盖静态,  **看多态
    		System.out.println("Zi static show");
    	}
    }
    
    输出结果
    Speak English!
    说中文
    打电话!
    Zi static show
    
    • 方法重写注意事项
      • 父类中私有方法不能被重写
        • 因为父类私有方法子类根本无法继承
      • 子类重写父类时,访问权限不能更低
        • 最好一致
      • 父类静态方法,子类也必须通过静态方法进行重写
        • 静态只能被覆盖
      • 子类重写父类的时候,最好声明一模一样
    • Override(方法重写)和overload(方法重载)区别
      • Overload可以改变返回值类型, 只看参数列表
      • 方法重写: 子类中出现和父类中方法声明一模一样的方法, 与返回值类型有关, 返回值是一致(或子父类)的
      • 方法重载: 本类中出现和方法名一样, 参数列表不同的方法, 与返回值类型无关
      • 子类调用对象的时候:
        • 先找子类本身, 再找父类

    final

    • final修饰特点
      • 修饰类, 类不能被继承
      • 修饰变量变量就成了常量, 只能被赋值一次
      • 修饰方法, 方法不能被重写
    package learn_javaSe;
    
    public class Demo37 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Test37 t1 = new Test37();
    		t1.print();
    		
    		double t2 = Test37.PI;	// 访问常量
    		System.out.println(t2);
    	}
    
    }
    class Demo37_Father{
    	public final void print() {
    		System.out.println("访问底层数据资源");
    	}
    	
    }
    
    /*
    class Demo37_Son extends Demo37_Father{
    	public void print() {
    		System.out.println("哈哈,功能被我干掉了");
    	}
    }
    */
    
    class Test37{
    	final int NUM = 10;  // 常量命名规范, 如果是一个单词, 所有字母大写,如果是多个中间用下划线隔开
    	public static final double PI = 3.14; // final 修饰变量被称为常量, 一般跟public static 更好的访问该常量
    	public void print() {
    		// num = 20;
    		System.out.println(NUM);
    	}
    }
    
    输出结果
    10
    3.14
    
    • 基本数据类型, 是之不能被改变的
    • 引用数据类型, 是地址值不能被改变的, 对象中的属性可以改变
    package learn_javaSe;
    
    public class Demo38 {
    
    	public static void main(String[] args) {
    		final int NUM = 10;
    //		NUM = 20;
    		System.out.println(NUM);
    		
    		final Demo38_Person p1 = new Demo38_Person("张三",18);
    //		p1  = new Demo38_Person("Vincent",19);
    		
    		p1.setName("Vincent");
    		p1.setAge(19);
    		
    		System.out.println(p1.getName() + "   " + p1.getAge());
    		
    		
    		method(10);
    		method(20);
    	}
    	
    	
    	public static void method(final int X) {
    		System.out.println(X);
    	}
    	
    
    }
    
    
    class Demo38_Person{
    	private String name;
    	private int age;
    	public Demo38_Person() {
    		
    	}
    	public Demo38_Person(String name, int age) {
    		this.name = name;
    		this.age = age;
    	}
    	
    	public void setName(String name) {
    		this.name = name;
    	}
    	
    	public String getName() {
    		return name;
    	}
    	
    	public void setAge(int age) {
    		this.age = age;
    	}
    	public int getAge() {
    		return age;
    	}
    }
    
    输出结果
    10
    Vincent   19
    10
    20
    
    
    • final修饰变量的初始化时
      • 显示初是化
      • 在对象构造完毕前即可
    package learn_javaSe;
    
    public class Demo39 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Test39 t1 = new Test39();
    		t1.print();
    	}
    
    }
    class Test39{
    	final int num1 = 10; // 显式初始化值
    	
    	
    //	final int num2;   // 成员变量默认初是化值是无效值
    	
    	final int num3;
    	public Test39() {
    		num3 = 20; // 在对象构造完成之前进行常量初始化
    	}
    	public void print() {
    		System.out.println(num1);
    		System.out.println(num3);
    	}
    }
    

    多态

    • 事物存在的多种形态
    • 多态前提
      • 要有继承关系
      • 要有方法重写
      • 要有父类引用指向子类对象
    public class Demo40 {
    
    	public static void main(String[] args) {
    		Demo40_Cat c = new Demo40_Cat();
    		c.eat();
    		
    		Demo40_Animal a = new Demo40_Cat();
    		a.eat();
    		
    	}
    
    }
    
    class Demo40_Animal{
    	public void eat() {
    		System.out.println("动物吃饭");
    	}
    }
    
    class Demo40_Cat extends Demo40_Animal{
    	public void eat() {
    		System.out.println("猫吃鱼");
    	}
    }
    
    • 多态中的成员访问特点

      • 成员变量
        • 编译看左边(父类), 运行看左边(父类)
      • 成员方法
        • 编译看左边(父类),运行看右边(子类) (动态绑定)
      • 静态方法
        • 编译看左边(父类), 运行看左边(父类)

      只有非静态成员方法, 编译看父类, 运行看子类

    package learn_javaSe;
    
    public class Demo41 {
    
    	public static void main(String[] args) {
    		Demo41_Father t = new Demo41_Son();		// 父类引用指向子类对象
    		System.out.println(t.num);
    		t.print();
    		t.method();		// 相当于Demo41_Father.method()
    		
    		Demo41_Son s = new Demo41_Son();
    		System.out.println(s.num);
    		s.print();
    		s.method();
    	}
    }
    class  Demo41_Father{
    	int num = 10;
    	public void print() {
    		System.out.println("father");
    	}
    	public static void method() {
    		System.out.println("static father");
    	}
    	
    }
    class Demo41_Son extends Demo41_Father{
    	int num = 20;
    	public void print() {
    		System.out.println("son");
    	}
    	public static void method() {
    		System.out.println("static son");
    	}
    }
    
    • 多态中向下转型和向上转型

    Person p = new SuperMan(); 向上转型

    SuperMan sm = (SuperMan)p; 向下转型

    package learn_javaSe;
    
    
    public class Demo42 {
    
    	public static void main(String[] args) {
    		Demo42_Person person = new Demo42_Superman();	// 父类引用指向子类对象, 超人提升为了人
    		person.谈生意();									// 父类引用指向子类对象就是向上转换
    		// person.fly();
    		Demo42_Superman superman = (Demo42_Superman) person;
    		superman.fly();									// 向下转型
    		/*
    		 * 基本数据类型自动类型提升和强制转换
    		 */
    		int i = 10;
    		byte b = 20;
    		i = b;	// 自动类型提升
    		b = (byte)i;	// 强制类型转换
    		
    		
    	}
    
    }
    
    class Demo42_Person{
    	String name = "John";
    	public void 谈生意() {
    		System.out.println("谈生意");
    	}
    }
    
    class Demo42_Superman extends Demo42_Person{
    	String name = "Superman";
    	
    	public void 谈生意() {
    		System.out.println("谈几个亿的大单子");
    	}
    	
    	public void fly() {
    		System.out.println("会飞");
    	}
    	
    }
    
    • 多态的好处

      • 提高代码的维护性(由继承保证)

      • 提高代码的扩展性(由多态保证)

        • 可以当作形式参数, 接受任意子类对象
        package learn_javaSe;
        
        public class Demo43 {
        
        	public static void main(String[] args) {
        //		Demo43_Cat c1 = new Demo43_Cat();
        //		c1.eat();
        		method(new Demo43_Cat());
        		method(new Demo43_Dog());
        		
        		// Animal a = new Dog(); // 开发的时候很少在创建对象的时候用父类引用指向子类对象
        		// 直接创建子类对象更方便,可以使用子类中的特有属性和行为
        	}
        	
        	/*
        	public static void method(Demo43_Cat c) {
        		c.eat();
        	}
        	public static void method(Demo43_Dog d) {
        		d.eat();
        	}
        	*/
        	
        	public static void method(Demo43_Animal a) {  // 当作参数的时候,用多态最好, 因为扩展性强
        		// a.eat();
        		// a.lookHome();		// 不能体现子类中特有的属性和行为
        		// 关键字 instaceof   判断前边的引用是否是后边的数据类型
        		if (a instanceof Demo43_Cat) {
        			((Demo43_Cat)a).eat();
        			((Demo43_Cat) a).catchMouse();
        		}else if (a instanceof Demo43_Dog) {
        			((Demo43_Dog)a).eat();
        			((Demo43_Dog)a).lookHome();
        			
        		}else {
        			a.eat();
        		}
        	}
        }
        
        class Demo43_Animal{
        	public void eat() {
        		System.out.println("动物吃饭");
        	}
        	
        }
        class Demo43_Cat extends Demo43_Animal{
        	public void eat() {
        		System.out.println("猫吃鱼");
        	}
        	public void catchMouse() {
        		System.out.println("抓老鼠");
        	}
        }
        class Demo43_Dog extends Demo43_Animal{
        	public void eat() {
        		System.out.println("狗吃肉");
        	}
        	public void lookHome() {
        		System.out.println("看家");
        	}
        }
        
    • 多态弊端

      • 不能使用子类的特有的属性和行为
    package learn_javaSe;
    
    public class Demo44 {
    
    	public static void main(String[] args) {
    		Demo44_Fu fu = new Demo44_Zi();
    //		fu.method();
    		fu.show();
    		
    	}
    
    }
    class Demo44_Fu{
    	public void show() {
    		System.out.println("fu show");
    	}
    }
    class Demo44_Zi extends Demo44_Fu{
    	/*
        public void show() {
    		System.out.println("zi show");
    	}
    	*/
    	public void method() {
    		System.out.println("zi method");
    	}
    }
    
    输出结果
    fu show
    

    抽象类的概述及其特点

    • 抽象就是看不懂

    • 抽象类的特点

      • 抽象类和抽象方法必须用abstract关键词修饰
        • abstract class 类名{}
        • public abstract void demo();
      • 抽象类不一定由抽象方法, 有抽象方法的类一定是抽象类或者是接口
      • 抽象类不能实例化
        • 按照多态的方式, 由具体的子类实例化, 其实这也是多态的一种, 抽象类多态
      • 抽象类的子类
        • 要么是抽象类
        • 要么重写抽象类中的所有抽象方
    • 抽象类成员特点

      • 成员变量,既可以是变量,也可以是常量, abstract不能修饰成员变量
      • 有构造方法, 用于子类访问父类数据的初始化
      • 抽象方法 强制要求子类做的事情
      • 非抽象方法 子类继承的事情, 提高代码复用性
    package learnjava;
    /**
    * @author Mephisto
    * @version 2018年7月27日 上午10:40:46
    */
    public class Demo3 {
    
    	public static void main(String[] args) {
    		Yue yue = new Yue();
    		yue.ziG();
    	}
    
    }
    
    abstract class AbstractKui{
    	public void ziG() {
    		System.out.println("用牙签");
    	}
    }
    
    class Yue extends AbstractDemo{
    	public void ziG() {
    		System.out.println("用指甲刀");
    	}
    }
    class Lin extends AbstractDemo{
    	public void ziG() {
    		System.out.println("用锤子");
    		
    	}
    }
    

    一个抽象类如果没有抽象方法, 可以有抽象类, 这么做的目的只有一个,就是不让其他类创建本类对象,交给子类完成

    abstract不能和那些关键字共存?

    • abstract 和static
    • 被abstract修饰的方法没有方法体
    • 被static修饰的可以用类名.调用,但是类名.抽象方法是没有意义的
    • abstract 和 final
    • 被abstract修饰的方法强制子类重写
    • 被final修饰的不让子类重写,所以他俩矛盾
    • abstract和private
    • 被abstract修饰的是为了让子类看到并强制重写
    • 被private修饰不让子类访问,所以他俩是矛盾的

    接口

    从狭义的角度, java中的interface

    从广义的角度, 对外提供规则的都是接口

    • 特点
      • 关键词interface
        • interface 接口名 {}
      • 类实现接口用implements表示
        • class 类名 implements 接口名 {}
      • 接口不能实现实例化
        • 按照多态的方式来实例化
      • 接口的子类
        • 可以是抽象类, 但是意义不大
        • 可以是具体类, 要重写接口中的所有抽象方法(推荐方案)
    package learnjava;
    /**
    * @author Mephisto
    * @version 2018年7月27日 下午2:28:48
    */
    public class Demo8 {
    
    	public static void main(String[] args) {
    		// Demo8Inter name = new // Demo8Inter();  // 接口不能被实例化, 因为调用抽象方法没有意义
    		Demo8Inter inter = new Demo8Test();	// 父类引用指向子类对象
    		inter.print();
    		
    	}
    
    }
    
    interface Demo8Inter{
    	/**
    	 * print
    	 */
    	public abstract void print();		//接口中的方法都是抽象的
    }
    
    class Demo8Test implements Demo8Inter{
    	@Override
    	public void print() {
    		System.out.println("这是类实现接口");
    	}
    }
    
    • 接口成员变量
      • 这能是常量, 并且是静态的并且是公共的
      • 默认修饰符 public static final
    • 接口是没有构造方法的 一个类如果不写继承任何类,默认继承Object类
    • 接口成员方法 只能是抽象的 默认修饰符 public abstract
    类与类, 类与接口, 接口与接口
    • 类与类
      • 继承关系, 只能单继承, 可以多层继承
    • 类与接口
      • 实现关系, 可以单实现, 也可以多实现
      • 并且还可以在继承一个类的同时实现多个接口
    • 接口与接口
      • 继承关系, 可以单继承, 也可以多层继承
    package learnjava;
    /**
    * @author Mephisto
    * @version 2018年7月27日 下午2:45:41
    */
    public class Demo10 {
    
    	public static void main(String[] args) {
    		Demo10Test test = new Demo10Test();
    		test.printA();
    		test.printB();
    	}
    
    }
    
    interface Demo10InterA{	
    	/**
    	 * printA
    	 */
    	void printA();
    }
    
    interface Demo10InterB{
    	/**
    	 * printB
    	 */
    	void printB();
    }
    
    interface Demo10InterC extends Demo10InterA,Demo10InterB{
    }
    
    
    
    class Demo10Test extends Object implements Demo10InterA,Demo10InterB{
    	@Override
    	public void printA() {
    		System.out.println("printA");
    	}
    	@Override
    	public void printB() {
    		System.out.println("printB");
    	}
    }
    
    
    抽象类和接口的区别
    • 成员区别
      • 抽象类:
        • 成员变量: 可以变量, 也可以常量
        • 构造方法: 有
        • 成员方法: 可以抽象, 也可以非抽象
      • 接口:
        • 成员变量: 只可以常量
        • 成员方法: 只可以抽象
    • 关系区别
      • 类与类
        • 继承, 单继承
      • 类与接口
        • 实现, 单实现, 多实现
      • 接口与接口
        • 继承, 单继承, 多继承
    • 设计理念区别
      • 抽象类 被继承体现的是 : "is a" 的关系, 抽象类中定义的是该继承体系中的共性功能
      • 接口 被实现体现的是:"like a" 的关系, 接口中定义的是该继承体系的扩展功能

    package关键字

    将字节码(.class)进行分类存放

    包其实就是文件夹

    域名倒写 com.xxxx.功能名(或模块名)

    • 分类
      • 按照功能划分
      • 按照模块划分
    • 定义包的格式
      • package 包名
      • 多级包用.分开
    • 定义包的注意事项
      • package语句必须是程序的第一条可执行的代码
      • package语句在一个java文件中只能有一个
      • 如果没有package, 默认表示无包名

    import关键字

    • import其实就是让有包的类对调用者可见,不用写全类名
    • package import class

    四种权限修饰符

    修饰符 本类 同一个包下(子类和无关类) 不同包下(子类) 不同包下(无关类)
    private Y
    默认 Y Y
    protected Y Y Y
    public Y Y Y Y
    • protected 关键字是只有这个类的子类可以访问
    • default即不写修饰符, 那就只有子类, 跟同一个包的类可以访问
    • private只有类本身可以访问
    • public 所有类都能访问

    类及其组成所使用的常见修饰符

    • 修饰符
      • 权限修饰符:private , default, protected, public
      • 状态修饰符:static , final
      • 抽象修饰符:abstract
      • 权限修饰符:default,public
      • 状态修饰符:final
      • 抽象修饰符:abstract
      • 用的最多的public
    • 成员变量
      • 权限修饰符: private default protected public
      • 状态修饰符: static final
      • 用的最多的private
    • 构造方法
      • 权限修饰符: private default protected public
      • 用的最多的 public
    • 成员方法
      • 权限修饰符 private default protected public
      • 状态修饰符 static final
      • 用的最多的 public
    • 除此以外的组合规则
      • 成员变量 public static final
      • 成员方法 public static

    内部类

    • 特点
      • 内部可以直接访问外部类的成员, 包括私有
      • 外部类需要访问内部类的成员必须创建对象
      • 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
    package learnjava;
    /**
    * @author Mephisto
    * @version 2018年7月28日 上午11:01:25
    */
    public class Demo12 {
    
    	public static void main(String[] args) {
    		/** 创建内部类对象 */
    		Outer12.Inner12 inner = new Outer12().new Inner12();  
    		inner.method();
    	}
    
    }
    
    class Outer12{
    	private int num = 10;
    	class Inner12{
    		public void method() {
    			System.out.println(num);
    		}
    	}
    }
    
    package learnjava;
    /**
    * @author Mephisto
    * @version 2018年7月28日 上午11:01:25
    */
    public class Demo12 {
    
    	public static void main(String[] args) {
    		/* 创建内部类对象 */
    //		Outer12.Inner12 inner = new Outer12().new Inner12();  
    //		inner.method();
    		
    		Outer12 outer12 = new Outer12();
    		outer12.print();
    	}
    
    }
    
    class Outer12{
    	private int num = 10;
        
        /* 成员方法被私有 */
    	private class Inner12{
    		public void method() {
    			System.out.println(num);
    		}
    	}
        
    	public void print() {
    		Inner12 inner12 = new Inner12();
    		inner12.method();
    	}
    }
    
    package learnjava;
    /**
    * @author Mephisto
    * @version 2018年7月28日 上午11:12:08
    */
    public class Demo13 {
    
    	public static void main(String[] args) {
    		
    		/** 外部类名.内部类名  对象名  = 外部类名.内部类对象; */
    		Outer13.Inner oInner = new Outer13.Inner();
    		oInner.method();
    		
    		Outer13.Inner2.print();
    
    	}
    
    }
    
    class Outer13 {
    	static class Inner{
    		public void method() {
    			System.out.println("method");
    		}
    	}
    	
    	
    	static class Inner2{
    		public static void print() {
    			System.out.println("print");
    		}
    	}
    }
    
    package learnjava;
    
    import java.io.IOError;
    
    /**
    * @author Mephisto
    * @version 2018年7月28日 上午11:19:42
    */
    public class Demo14 {
    
    	public static void main(String[] args) {
    		Outer14.Inner14 oi = new Outer14().new Inner14();
    		oi.show();
    
    	}
    
    }
    
    class Outer14{
    	public int num = 10;
    	class Inner14{
    		public int num = 20;
    		public void show() {
    			int num = 30;
    			/** 要求: 使用已知的变量,在控制台输出10,20,30 */
    			/*
    			 * 内部类之所以能够获取到外部类的成员, 是因为他能获取到外部类的引用外部类名.this
    			 */
    			System.out.println(Outer14.this.num);
    			System.out.println(this.num);
    			System.out.println(num);;
    		}
    	}
    }
    

    局部内部类访问局部变量的问题

    • 局部内部类访问局部变量必须使用final修饰
    • 局部内部类在访问他所在的方法中的局部变量必须使用final修饰
    • 因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果这个局部内部类对象还没有马上消失享用这个局部变量,就没有了,如果final修饰会在类加载的时候进入变量池,即使方法弹栈,常量池的常量还在,也可以继续使用
      • 在jdk1.8取消了这件事

    匿名内部类

    • 就是内部类的简化写法

    • 前提: 存在一个类或接口(这里的类可以事具体类也可以是抽象类

    • 格式:

      new 类名或者接口名(){   
          重写方法; 
      }
      
    • 本质

      • 是一个继承类该类或者实现了该接口的子类匿名对象
    package learnjava;
    /**
    * @author Mephisto
    * @version 2018年7月28日 上午11:44:12
    */
    public class Demo16 {
    
    	public static void main(String[] args) {
    		Outer16 o = new Outer16();
    		o.method();
    
    	}
    
    }
    interface Inter16{
    	/**
    	 * print
    	 */
    	abstract void print();
    	
    }
    
    class Outer16 {
    	/*
    	class Inner16 implements Inter16{
    		@Override
    		public void print() {
    			System.out.println("print");
    		}
    	}
    	*/
    	public void method(){
    		/**
    		Inner16 inner16 = new Inner16();
    		inner16.print();
    		*/
    		new Inter16() {			// 实现Inter16 接口	
    			@Override			// 重写方法
    			public void print() {
    				System.out.println("Hello world!");
    			}
    		}.print();
    	}
    	
    }
    
    package learnjava;
    /**
    * @author Mephisto
    * @version 2018年7月28日 上午11:58:53
    */
    public class Demo18 {
    
    	public static void main(String[] args) {
    		Outer18 o = new Outer18();
    		o.method();
    	}
    
    }
    interface Inter18{
    	public abstract void show1();
    	public abstract void show2();
    	
    }
    
    /** 匿名内部类只针对重写一个方法时候使用  */
    class Outer18{
    	public void method(){
    		/**
    		new Inter18() {
    			
    			@Override
    			public void show2() {
    				System.out.println("show2");
    			}
    			
    			@Override
    			public void show1() {
    				System.out.println("show1");
    			}
    		}.show1();
    		new Inter18() {
    			
    			@Override
    			public void show2() {
    				System.out.println("show2");
    			}
    			
    			@Override
    			public void show1() {
    				System.out.println("show1");
    			}
    		}.show2();
    		*/
    		
    		Inter18 i = new Inter18() {
    			
    			@Override
    			public void show2() {
    				System.out.println("show2");
    			}
    			
    			@Override
    			public void show1() {
    				System.out.println("show2");
    			}
    			
    			/*
    			public void show3() {
    				System.out.println("show3");
    			}
    			*/
    		};
    		i.show1();
    		i.show2();
    //		i.show3();	// 匿名内部类不能向下强转, 因为没有子类类名
    		
    		
    	}
    }
    
  • 相关阅读:
    mysql导入导出sql文件
    linux 监控文件变化
    LeetCode:595.大的国家
    LeetCode:176.第二高的薪水
    LeetCode:182.查找重复的电子邮箱
    Excel学习笔记:行列转换
    通过数据分析题目实操窗口函数
    Oracle学习笔记:窗口函数
    Python学习笔记:利用爬虫自动保存图片
    电商数据分析基础指标体系(8类)
  • 原文地址:https://www.cnblogs.com/mephisto03/p/9381651.html
Copyright © 2020-2023  润新知