- 代码块:使用{ }定义的一段代码。
根据代码块定义的位置以及关键字,又可分为以下四种:
• 普通代码块:定义在方法中的代码块
• 构造块:定义在类中的代码块(不加修饰符)
• 静态块:使用static定义的代码块
• 同步代码块 - 构造块优先于构造方法执行,每产生一个新的对象就调用一次构造块,构造块可以进行简单的逻辑操作。
class Person {
{
System.out.println("1.Person类的构造块");
}
public Person() {
System.out.println("2.Person类的构造方法");
}
}
public class Test {
public static void main(String[] args) {
new Person();
new Person();
}
}
- 根据静态块所在的类的不同可分为以下两种类型:
1)在非主类中:
①静态块优先于构造块执行,但是不优先于主方法(main)执行;
②无论产生多少实例化对象,静态块都只执行一次。
2)在主类中:
在主类中定义的静态块,优先于主方法(main)执行。 - 内部类:所谓的内部类就是在一个类的内部进行其他类结构的嵌套的操作。
- 内部类存在的意义:
1)内部类方法可以访问该类定义所在作用域中的数据,包括被private修饰的私有数据;
2)内部类可以对同一包中的其他类隐藏起来;
3)内部类可以实现java单继承的缺陷;
4)当我们想要定义一个回调函数却不想写大量代码的时候,我们可以选择使用匿名内部类来实现。 - 内部类是一个相对独立的实体,内部类可以直接访问外部类的元素(包含私有域),但是外部类不可以直接访问内部类的元素,外部类可以通过内部类引用间接访问内部类元素。
//内部类直接访问外部类元素
class Outter {
private String name;
private int age;
class Inner {
private int InnerAge;
public Inner() {
Outter.this.outName = "I am Outter class";
Outter.this.outAge = 20;
}
public void display() {
System.out.println(outName);
System.out.println(outAge);
}
}
}
//外部类可以通过内部类引用间接访问内部内元素
class Outter {
public void display() {
//外部类访问内部类元素,需要通过内部类引用来访问
Inner in = new Inner();
in.display();
}
class Inner {
public void display(0 {
System.out.println("I am InnerClass");
}
}
}
- 内部类分为:
1)实例(成员)内部类——依赖于外部类对象
2)静态内部类
3)方法内部类
4)匿名内部类 - 创建内部类对象的方法:
- 在使用内部类的时候创建内部类对象:
外部类.内部类 内部类对象 = new 外部类().new 内部类();
Outer.Inner in = new Outter(0.new Inner();
- 在外部类内部创建内部类对象:
Inner in = new Inner();
- 实例(成员)内部类的相关问题:
1)实例(成员)内部类不能存在任何static的变量和方法;
2)实例(成员)内部类是依附于外部类的,只有先创建了外部类才能创建内部类。
3)实例内部类能否定义static的内部成员?
用final修饰,如果一个数被final所修饰,则该值在编译期间就确定了,不依赖于对象。例如:public static final int A = 10;
4)实例内部类对象是否有额外的内存消耗?
有,实例内部类拥有外层的this引用。(实例内部类在编译完成后会隐含地保存着一个引用,该引用是指向创建它的外围类。) - 静态内部类(static修饰的内部类):
1)静态内部类的创建不需要依赖于外围类,可以直接创建;
2)静态内部类一般情况下不可以使用任何外围类的非static成员变量和方法。
3)静态内部类能否访问外部类的实例成员?
可以,在主方法创建一个外部类对象,再将外部类对象传到静态内部类的构造方法中,在静态内部类执行中获得外部类对象,从而通过外部类对象调用外部类属性达到访问外部类属性的功能。
//静态内部类的定义
class Outter {
private static String msg = "Hello";
static class Inner { //定义静态内部类
public void print(0 {
System.out.println(msg); //调用msg属性
}
}
//在外部类定义一个方法,该方法负责产生内部类对象并调用print()方法
public void fun() {
Inner in = new Inner();
in.print();
}
}
- 方法(局部)内部类:定义在外部类的方法中
1)局部内部类不允许使用访问权限修饰符 public private protected ;
2)局部类除了创建这个类的方法可以访问它,其他的地方不允许访问它;
3)局部内部类想要使用方法形参,该形参必须使用final声明(JDK8形参变为隐式final声明)。
//方法内部类
class Outter {
private int num;
public void display(int text) {
//方法内部类的定义
class Inner {
private void fun() {
num ++;
System.out.println(num);
System.out.println(text)'
}
}
new Inner().fun();
}
}
- 匿名内部类:没有名字的方法内部类 用于回调方法
1)匿名内部类没有访问修饰符;
2)匿名内部类必须继承一个抽象类或实现一个接口;
3)匿名内部类中不能存在任何静态成员或方法;
4)匿名内部类没有构造方法,因为它无类名;
5)若引用方法形参,形参必须声明为final。
//匿名内部类
interface MyInterface { //接口
void test();
}
class Outter {
private int num;
public void display(int para) {
//匿名内部类,实现MyInterface接口
new MyInterface() {
//重写test方法
public void test() {
System.out.println("匿名内部类"+para);
}
}.test();
}
}
- 内部类总结:方便进行私有属性的访问,类名称上出现了. ,应当想到内部类的概念。
- 继承:主要作用是代码的重用,和在已有基础上继续进行功能的扩充。
- 继承的实现:使用关键词extends来实现继承,定义语法为:
class 子类(派生类) extends 父类(基类/超类)
- 派生类(子类)继承了基类(父类)除构造方法外的所有结构。
- 子类对象在进行实例化前一定会首先实例化父类对象。默认调用父类的构造方法后再调用子类构造方法进行子类对象初始化。
- 在子类的构造方法中,隐含了一个super();如果父类里没有提供无参构造,这个时候必须使用super()明确指明你要调用的父类构造方法。
- java不允许多重继承,但是允许多重继承。所有的非私有操作属于显示继承(可以直接调用),所有的私有操作属于隐式继承(通过其他形式调用,例如setter和getter方法)。
- 覆写(override):子类定义了与父类相同的方法或属性的时候,这样的操作就称为覆写。(协变类型:返回值之间如果可以构成继承关系也称为覆写。)
- 方法的覆写:子类定义了与父类方法名称相同,参数类型和参数列表相同,返回值相同的方法。Ps:被覆写不能够拥有比父类更为严格的访问控制权限。
控制访问权限:private<default(包访问权限)<public
如果父类使用public进行方法声明,那么子类必须也使用public;如果父类使用default,那么子类可以使用default或者public。
- 重载(overload):方法名称相同,参数的类型及个数不同,返回值不做要求,范围在一个类中,没有权限要求。
- super关键字:
1)super(); //调用基类(父类)的构造方法
2)super.方法(); //调用基类(父类)的方法
3)super.属性; //调用基类(父类)的属性 - super和this的区别:
●this是本类的访问处理操作,访问本类中的属性和方法,先查找本类,如果本类没有就调用父类,表示当前对象。
●super是派生类(子类)访问基类(父类)的操作,由子类访问父类中的属性、方法,不查找本类而直接调用。
- final关键字:(终结器)
1)final可以修饰类、方法、属性;
2)final成员变量必须在声明的时候初始化或者在构造器中初始化,否则会出现编译出错;
3)使用final定义的类不能有子类(String类便是使用final定义),被称为密封类,不可被继承;
4)final一旦修饰一个类之后,该类的所有方法默认都会加上final修饰(不包含成员变量)
5)final定义的方法不能被子类所覆写;
6)final定义的变量就成为了常量,常量必须在声明时赋值,并且不能被修改;
7)final修饰的变量不能再次赋值;
8)定义常量全部用大写字母,多个单词间以_分隔,例如:
public static final int MAX_AGE = 120;
- 多态:基类(父类)引用,引用派生类(子类)对象,并且基类和派生类有同名的覆写方法;
- 对象的多态性的前提和核心是:方法覆写。
- 对象的向上转型: 父类 父类对象 = 子类实例。
Person per = new Student();
- 对象的向下转型: 子类 子类对象 = (子类)父类实例。
Person per = new Person(); Student stu = (Student) per;
- 向下转型存在安全隐患,可以依靠instanceof关键字实现,语法如下:
子类对象 instanceof 类,返回boolean类型
if (per instanceof Student) { //避免ClassCastException
Student stu = (Student) per;
}