Java笔记:面向对象(下)

static关键字

  • 可以用来修饰属性,方法,代码块,内部类
修饰属性

属性按照是否使用static修饰,又分为:静态属性(类变量) vs 非静态属性(实例变量)

  • 非静态变量:创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性,当修改其中一个对象中的非静态属性时,不会导致其他对象中同样的其他属性值的修改
  • 静态变量:创建了类的多个对象,多个对象共享同一个静态变量,当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过的变量
  • 静态变量随着类的加载而加载,可以通过类.静态变量的方式进行调用
  • 静态变量的加载要早于对象的创建
  • 由于类只加载一次,静态变量在内存中也只存在一份:存在方法区的静态域中
修饰方法
  • 随着类的加载而加载,可以通过类.静态方法来调用
  • 静态方法中只能调用静态的方法或属性
  • 非静态方法中既可以调用非静态结构,也可以调用静态结构
  • 在静态的方法内,不能够使用this和super关键字
使用场景
  • 属性何时要声明为static
    1. 属性可以被多个对象所共享的,不会随着对象的不同而不同
    2. 类中的常量也常常声明为静态的
  • 方法何时要声明为static
    1. 操作静态属性的方法通常设置为静态的
    2. 工具类中的方法,习惯上声明为静态方法

main()方法的说明

  • main()方法是程序的入口
  • main()方法也是一个普通的静态方法,可以正常的通过类来调用
  • main()方法也可以作为与控制台交互的方式
    1. 使用idea或eclipse的话,选择 Edit Configurations,编辑带有arguments的项,输入参数,多个参数之间用空格分隔,加不加双引号都可以,再运行就可以使用传入的参数
    2. 使用控制台的话,先使用javac编译,在运行的时候使用java class名 参数1 参数2 ......,参数加不加双引号都可以

代码块

  • 作用:用来初始化类、对象
  • 结构:{}(如果有修饰,只能用static)
  • 分类:静态代码块 vs 非静态代码块
  • 静态代码块:
    1. 内部可以有输出语句
    2. 随着类的加载而执行,且只执行一次
    3. 作用:初始化类的信息
    4. 如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
    5. 静态代码块的执行要优先于非静态代码块
    6. 静态代码块内只能调用静态的结构
  • 非静态代码块:
    1. 内部可以有输出语句
    2. 随着对象的创建而执行
    3. 每创建一个对象,就执行一次非静态代码块
    4. 作用:可以在创建对象时,对对象的属性等进行初始化
    5. 如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
    6. 非静态代码块内既可以调用静态的结构,也可以调用非静态的结构
属性赋值的先后顺序
默认初始化
显式初始化 / 代码块中赋值
构造器中赋值
通过对象调用属性或方法来赋值

final关键字

  • final可以修饰类、方法、变量
    1. final修饰类:此类就不可以被其他类所继承(String、System、StringBuffer)
    2. final修饰方法:此方法不可以被重写(Object中的getClass()方法)
    3. final修饰变量:此时的变量就称为是一个常量
  • static final可以修饰属性、方法,修饰属性表示该属性是全局常量
  • final修饰属性时可以赋值的条件:显式初始化、代码块中赋值、构造器中赋值
  • final修饰局部变量:尤其是使用final来修饰形参时,表明此形参是一个常量。当调用此方法时,给常量形参赋一个实参。一旦赋值以后,就只能在方法体内使用此形参,不能重新进行赋值

abstract关键字

  • 可以用来修饰类、方法
  • 抽象类:
    1. 此类不能实例化(不能够创建对象)
    2. 开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作
    3. 抽象类中一定有构造器,便于子类对象实例化时调用
  • 抽象方法:
    1. 抽象方法只有方法的声明,没有方法体
    2. 包含抽象方法的类一定是一个抽象类,但抽象类中可以没有抽象方法
    3. 子类重写了父类中的所有的抽象方法以后,该子类才可以实例化,否则该子类也要是一个抽象类
  • abstract使用注意
    1. 不能用来修饰属性、构造器等结构
    2. 不能用来修饰私有方法,静态方法、final的方法、final的类
  • 抽象类的匿名子类
    // 如果Person是一个抽象类
    Person p = new Person() {
    	// 重写抽象方法
    };
    

接口(interface)

接口就是规范,定义的是一组规则。接口的本质是契约,标准,规范。

  • Java中,接口和类是并列的两个结构
  • 接口的成员:
    1. JDK7及以前:只能定义全局常量和抽象方法(相关关键字可以省略不写)
    2. JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法和默认方法
    interface Flyable {
    
        public static final int MAX_SPEED = 7900;
        int MIN_SPEED = 1;
    
        public abstract void fly();
        void stop();
    
    }
    
  • 接口中不能定义构造器,意味着接口不可以实例化
  • 开发中,接口都通过让类去实现的方式来使用。如果实现类覆盖了接口中所有的抽象方法,该实现类就可以实例化,否则该实现类仍为一个抽象类(面向接口编程)
  • Java类可以实现多个接口,弥补了Java单继承性的局限性
    格式:class AA extends BB implements CC,DD,EE {}
  • 接口与接口之间可以继承,而且可以多继承
  • 接口的具体使用,提现多态性
  • 接口的匿名实现类
    Flyable f = new Flyable() {
    	// 覆盖抽象方法
    };
    

JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法和默认方法

public interface CompareA {

	// 静态方法
	public static void method1() {
		System.out.println("CompareA中的静态方法");
	}

	// 默认方法:public可以省略
	public default void method2() {
		System.out.println("CompareA中的默认方法");
	}

}
public class SubClassTest {
	public static void main(String[] args) {
		SubClass s = new SubClass();
		s.method2();// 默认方法
		CompareA.method1();// 静态方法
	}
}

class SubClass implements CompareA {
	public void method2() {
		System.out.println("CompareA中的默认方法的重写");
		CompareA.super.method2();// 调用接口中的默认方法
	}
}

注意:

  1. 接口中定义的静态方法只能通过接口来调用
  2. 接口中定义的默认方法可以通过实现类的对象来调用,如果实现类重写了接口中的默认方法,那么在实现类调用时调用的是重写的方法
  3. 如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的方法,那么子类在没有重写此方法的情况下,默认调用的是父类中的该方法(类优先原则)
  4. 如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,则在实现类没有重写该方法的情况下,会报错(接口冲突),这需要在实现类中重写此方法

内部类

当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。

  • 分类:成员内部类(静态、非静态) vs 局部内部类(方法、代码块、构造器)
  • 成员内部类和局部内部类在编译后都会生成字节码文件

成员内部类:

  • 作为外部类的成员:
    1. 调用外部类的结构
    2. 可以用static修饰
    3. 可以被4种不同的权限修饰
  • 作为一个类:
    1. 类的内部可以定义属性、方法、构造器等
    2. 可以被final修饰,表示此类不能被继承
    3. 可以被abstract修饰,表示此类不能被实例化

如何实例化成员内部类

public static void main(String[] args) {
	// 创建Dog实例(静态成员内部类)
	Person.Dog dog = new Person.Dog();
	dog.show();
	// 创建Bird实例(非静态成员内部类)
	Person person = new Person();
	Person.Bird bird = person.new Bird();
	bird.sing();
}

如何在成员内部类中区分调用外部类的结构

public void display(String name) {
	// 如果属性名和方法名没有冲突,可以直接调用
	System.out.println(name);// 方法的形参
	System.out.println(this.name);// 内部类的属性
	System.out.println(Person.this.name);// 外部类的属性
}

开发中局部内部类如何使用

// 返回一个实现了Comparable接口的类的对象
public Comparable getComparable() {
	// 创建一个实现了Comparable接口的类:局部内部类
	class MyComparable implements Comparable {

		@Override
		public int compareTo(Object o) {
			// TODO Auto-generated method stub
			return 0;
		}

	}
	return new MyComparable();
}
// 方式二:
public Comparable getComparable() {
	return new Comparable() {
		@Override
		public int compareTo(Object o) {
			// TODO Auto-generated method stub
			return 0;
		}
	};
}

内部类代码

class Person {

	String name;
	int age;

	public void eat() {
		System.out.println("人:吃饭");
	}

	// 静态成员内部类
	static class Dog {
		String name;
		int age;

		public void show() {
			System.out.println("卡拉是条狗");
		}
	}

	// 非静态成员内部类
	class Bird {
		String name;

		public Bird() {
			super();
		}

		public void sing() {
			System.out.println("我是一只小小鸟");
			Person.this.eat();// 调用外部类的非静态的结构
		}
	}

	public Person() {
		// 局部内部类
		class C {

		}
	}

	{
		// 局部内部类
		class B {

		}
	}

	public void method() {
		// 局部内部类
		class A {

		}
	}

}

在局部内部类的方法中,如果调用局部内部类所声明的方法中的局部变量的话,要求此局部变量声明为final的

public void method() {
	int num = 10;// 此时默认为final的;在JDK7之前要求该变量要显式声明为final的
	class AA {
		public void show() {
			System.out.println(num);
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值