一、代码块
代码块是使用{}定义的一段代码
代码块分为普通代码块、构造块、静态块和同步代码块
1.普通代码块
定义在方法中的代码块,若方法中代码较长,为避免变量重名,使用普通代码块进行分隔
2.构造块
定义在类中的代码块(不加修饰符)
注:构造块优先于构造方法执行,每产生一个新的对象就调用一次构造块,构造块可以进行简单的逻辑操作
3.静态代码块
使用static定义的代码块
(1)在非主类中的静态代码块
1)静态块优先于构造块执行。
2)无论产生多少实例化对象,静态块都只执行一次。
(2)在主类中的静态代码块
在主类中定义的静态块,优先于主方法(main)执行
class Person
{
{
System.out.println("1.类中的构造块");
}
public Person() {
System.out.println("2.类中的无参构造,代码块");
}
public Person(int i) {
System.out.println("3.类中的有参构造,代码块");
}
static {
System.out.println("4.类中的静态块");
}
}
public class Test {
{
System.out.println("5.主类中的代码块");
}
public Test() {
System.out.println("6.主类中的无参构造");
}
static
{
System.out.println("7.主类中的静态块");
}
public static void main(String[] args) {
System.out.println("————start————");
Test test1=new Test();
Test test2=new Test();
Person per1=new Person();
Person per2=new Person();
Person per3=new Person(2);
Person per4=new Person(3);
System.out.println("———— end ————");
}
}
上面这段代码执行的结果为
7.主类中的静态块
————start————
5.主类中的代码块
6.主类中的无参构造
5.主类中的代码块
6.主类中的无参构造
4.类中的静态块
1.类中的代码块
2.类中的无参构造,构造块
1.类中的代码块
2.类中的无参构造,构造块
1.类中的代码块
3.类中的有参构造,构造块
1.类中的代码块
3.类中的有参构造,构造块
———— end ————
————start————
5.主类中的代码块
6.主类中的无参构造
5.主类中的代码块
6.主类中的无参构造
4.类中的静态块
1.类中的代码块
2.类中的无参构造,构造块
1.类中的代码块
2.类中的无参构造,构造块
1.类中的代码块
3.类中的有参构造,构造块
1.类中的代码块
3.类中的有参构造,构造块
———— end ————
二、内部类
内部类的特点:
(1)破坏了程序的结构
(2)方便进行私有属性的访问。(外部类也可以访问内部类的私有域)
(3)如果发现类名称上出现了".",应当立即想到内部类的概念。
(2)方便进行私有属性的访问。(外部类也可以访问内部类的私有域)
(3)如果发现类名称上出现了".",应当立即想到内部类的概念。
因此,内部类不作为设计的首选
内部类就是在一个类的内部进行其他类结构的嵌套的操作
class Outter
{
private String msg= "Hello World";
class Inner
{
public void print()
{
System.out.println(msg);
}
}
//需要在内部类外,外部类中定义一个方法,来将内部类进行实例化
public void fun()
{
Inner inner=new Inner();
inner.print();
}
}
public class Test
{
public static void main(String[] args)
{
Outter outter=new Outter();
outter.fun();
}
}
(1)如果想在程序外部调用,那么必须按照如下形式进行内部类的实例化对象创建
外部类.内部类 内部类对象 = new 外部类().new 内部类();
Outter.Inner in = new Outter().new Inner();
(2)如果说现在一个内部类只想被外部类使用,即:不希望直接产生内部类的实例化对象,可以使用private定义
(3)在进行属性访问时,都需要加上this关键字。所以如果想在内部类中明确的使用this,则格式为
外部类.this.属性
1.static定义内部类
内部类中如果使用了static进行定义。该内部类只允许访问外部类中的static操作。实际上该内部类等同于外部类,产生该内部类的实例化对象语法为
外部类.内部类 内部类对象 = new 外部类.内部类();
class Outter
{
private static String msg= "Hello World";
static class Inner
{
public void print()
{
System.out.println(msg);
}
}
public void fun() {
Inner inner=new Inner();
inner.print();
}
}
public class Test {
public static void main(String[] args) {
Outter.Inner inner=new Outter.Inner();
inner.print();
}
}
2.在方法中定义内部类(最常用)
class Outter
{
private String msg="Hello word";
public void fun() {
class Inner
{
public void print()
{
System.out.println(msg);
}
}
//在方法外部要将内部类进行实例化,并调用方法
Inner inner=new Inner();
inner.print();
}
}
public class Test {
public static void main(String[] args) {
Outter outter=new Outter();
outter.fun();
}
}
三、继承
面向对象的第二大特征:继承。
1)
继承的主要作用在于,消除结构定义上的重复,在已有基础上继续进行功能的扩充,以及代码的重用。
2)子类对象的实例化流程:不管如何操作,一定要先实例化父类对象。
3)不允许多重继承,只允许多层继承。
2)子类对象的实例化流程:不管如何操作,一定要先实例化父类对象。
3)不允许多重继承,只允许多层继承。
1.继承的实现
继承使用extends关键字来实现,子类也称为派生类,父类也称为超类
class 子类 extends 父类
class Person
{
private String name;
private int 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;
}
}
class Student extends Person
{
private String sex;
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
public class Test {
public static void main(String[] args) {
Student student=new Student();
student.setName("LLL");
student.setAge(11);
student.setSex("m");
System.out.println("name"+student.getName()+"age"+student.getAge()+"sex"+student.getSex());
}
}
当发生了类继承关系之后,子类可以直接继承父类的操作,可以实现代码的重用
2.继承的限制
(1)子类对象在进行实例化前一定会首先实例化父类对象。默认调用父类的构造方法后再调用子类构造方法
进行子类对象初始化
进行子类对象初始化
(2)如果父类里没有提供无参构造,那么这个时候就必须使用super()明确指明你要调用的父类构造
方法
方法
class Person
{
public Person() {
System.out.println("1父类无参构造");
}
public void print() {
System.out.println("2父类的普通方法");
}
}
class Student extends Person
{
public Student() {
super.print();//指明了这个构造方法继承的是父类的print方法
//若此句不写,则student类就是一个普通类,就不是person类的子类
System.out.println("3子类的无参构造");
}
public Student(int i) {
System.out.println("4子类的有参构造");
}
public void fun()
{
super.print();
System.out.println("5子类的普通方法");
}
}
public class Test {
public static void main(String[] args) {
Student student1=new Student();//1 2 3
Student student2=new Student(1);//1 4
student1.fun();//2 5
}
}
3.Java不允许多重继承,但是允许多层继承
(1)一个子类只能继承一个父类,C同时继承A和B的主要目的是同时拥有A和B中的操作,为了实现这样的目的,可以采用多层继承的形式完成
class A{}
class B extends A{}
class C extends B{}
class B extends A{}
class C extends B{}
(2)在进行继承的时候,子类会继承父类的所有结构。(包含私有属性、构造方法、普通方法)但是这个时候需要注意的是,所有的非私有操作属于显示继承(可以直接调用),所有的私有操作属于隐式继承(通过其他形式调用,例如setter或getter)
四、覆写
如果子类定义了与父类相同的方法或属性的时候,这样的操作就称为覆写
1.方法的覆写
子类定义了与父类方法名称、参数类型及个数完全相同的方法称为覆写。但是被覆写不能够拥有比父类更为严格的访问控制权限。
(1)覆写的语句
class Person{
public void print()
{
System.out.println("1父类的普通方法");
}
}
class Student extends Person
{
public void print()
{
System.out.println("2子类对父类普通方法print的覆写");
}
}
public class Test
{
public static void main(String[] args)
{
Student student=new Student();//2
student.print();
}
}
1)只需要关注当前使用的对象是通过哪个类new的。
2)当调用某个方法,如果该方法已经被子类所覆写了,那么调用的一定是被覆写过的方法。
(2)覆写的权限
在进行方法覆写的时候,有明确的要求:被覆写不能够拥有比父类更为严格的访问控制权限。现在,见到的权限比较有private<default<public。那么也就意味着如果父类使用public进行方法声明,那么子类必须也使用public;如果父类使用default,那么子类可以使用default或者public。也就是说,覆写的子类方法的权限一定要大于等于被覆写的父类的方法权限。
注:父类使用private定义的方法,子类不能覆写
class Person
{
private void print()
{
//如果父类的方法是用private定义,则表示该方法只能被父类使用,子类无法覆写
System.out.println("2父类的普通方法");
}
}
class Student extends Person
{
public void print()
{
//此时只是在子类中重新定义了一个叫print的方法,根本没有对父类进行覆写
System.out.println("子类想要对父类普通方法print的覆写,结果覆写失败");
}
}
public class Test
{
public static void main(String[] args)
{
Student student=new Student();
student.print();
}
}
(3)覆写与重载的区别
2.属性的覆写
当子类定义了和父类属性名称完全相同的属性的时候,就成为属性的覆盖
class Person
{
public String name="LLL";
}
class Student extends Person
{
public String name ="HHH";
}
public class Test
{
public static void main(String[] args)
{
Student student=new Student();
System.out.println("name"+student.name);
}
}
3.super关键字
(1)在继承时,子类调用父类构造方法时使用
(2)在进行覆写时使用 super.方法() 或者 super.属性 明确调用父类中的方法或属性
class Person
{
public String mString="父类属性";
public void print()
{
System.out.println("父类方法");
}
}
class Student extends Person
{
public String mString="子类属性";
public void print()
{
super.print();//在子类方法中调用父类方法
System.out.println(super.mString);//在子类方法中调用父类属性
System.out.println("子类方法");
System.out.println(this.mString);
}
}
public class Test
{
public static void main(String[] args)
{
Student student=new Student();
student.print();
}
}
(3)this关键字和super关键字的区别
注:能使用super.方法()一定要明确标记出是父类的操作
(1)子类覆写父类的方法是因为父类的方法功能不足才需要覆写。
(2)方法覆写的时候使用的就是public权限
(2)方法覆写的时候使用的就是public权限
五、final关键字
在Java中final被称为终结器,可以使用final来定义类、方法、属性。
(1)
使用final来定义类
使用final定义的类不能有子类(String类便是使用final定义)
使用final定义的类不能有子类(String类便是使用final定义)
final class A{} //A类不能有子类
(2)
使用final来定义方法
使用final定义的方法不能被子类所覆写。
使用final定义的方法不能被子类所覆写。
class A{
public final void fun(){}
}
public final void fun(){}
}
(3)
使用final来定义属性
使用final定义的变量就成为了常量,常量必须在声明时赋值,并且不能够被修改。
使用final定义的变量就成为了常量,常量必须在声明时赋值,并且不能够被修改。
publc final int LEVEL_A = 100 ;
六、多态性
1. 方法的多态性
(1)方法的重载:同一个方法名称可以根据参数的类型或个数不同调用不同的方法体
(2)方法的覆写:同一个父类的方法,可能根据实例化子类的不同也有不同的实现。
2. 对象的多态性【抽象类和接口才能体会到实际用处】(前提:方法覆写):
(2)方法的覆写:同一个父类的方法,可能根据实例化子类的不同也有不同的实现。
2. 对象的多态性【抽象类和接口才能体会到实际用处】(前提:方法覆写):
【自动,90%】①对象的向上转型:父类 父类对象 = 子类实例。
【强制,1%】②对象的向下转型:子类 子类对象 = (子类)父类实例。
【强制,1%】②对象的向下转型:子类 子类对象 = (子类)父类实例。
(1)向上转型
class Person
{
public void print()
{
System.out.println("1.父类普通方法");
}
}
class Student extends Person
{
public void print()
{
System.out.println("2.子类普通方法对父类进行覆写");
}
}
public class Test {
public static void main(String[] args) {
Person person=new Student();//向上转型
person.print();
}
}
(2)向下转型
向下转型指的是将父类对象变为子类对象,当需要子类扩充操作的时候就要采用向下转型
class Person
{
public void print()
{
System.out.println("1.父类普通方法");
}
}
class Student extends Person
{
public void print()
{
System.out.println("2.子类普通方法对父类进行覆写");
}
public void fun()
{
System.out.println("子类特有的方法");
}
}
public class Test {
public static void main(String[] args) {
Person person=new Student();//向上转型(自动)
person.print();
Student student=(Student) person;//向下转型(强转)在向下转型之前,一定要进行向上转型
student.fun();
}
}
若向下转型具有安全隐患,则需要用instanceof关键字进行判断
public class Test {
public static void main(String[] args) {
Person person=new Student();//向上转型(自动)
person.print();
if(!(person instanceof Student ))
{
person =new Student();
Student student=(Student) person;
student.fun();
}
}
注:
(1)对象多态性的核心在于方法的覆写。
(2)通过对象的向上转型可以实现接收参数的统一,向下转型可以实现子类扩充方法的调用
(2)两个没有关系的类对象是不能够进行转型的,一定会产生ClassCastException。
(2)通过对象的向上转型可以实现接收参数的统一,向下转型可以实现子类扩充方法的调用
(2)两个没有关系的类对象是不能够进行转型的,一定会产生ClassCastException。