java基础知识总结(二)

# java基础知识总结(二)

面向对象(object oriented program)

一、基本内容

1.1面向对象

1.1.1什么是面向对象和面向过程?

什么是面向过程?:完成一个功能时,功能的每一个步骤,都需要我们进行参与,每一个细节都需要了解清楚,才能完成。强调的是过程。(先干什么,后干什么(先有算法,后有数据结构))
什么是面向对象?:强调的是通过调用对象的行为来实现功能,而不是自己一步一步的去操作实现。(先有数据结构,后有算法)Java语言是一种纯面向对象的程序设计语言(必须要编写类才能执行。),而面向对象思想是一种程序设计思想,我们在面向对象思想的指引下, 使用Java语言去设计、开发计算机程序。 这里的对象泛指现实中一切事物,每种事物都具备自己的属性行为在计算机程序设计过程中,参照现实中事物,将事物的属性特征、行为特征抽象出来,描述成计算机事件的设计思想。它区别于面向过程思想,强调的是通过调用对象的行为来实现功能,而不是自己一步一步的去操作实现。(先有数据结构,后有算法。)
(客观的)对象抽象成一个(主观的)类。

1.1.2面向对象的特点?

1.符合了我们人类思考习惯的思想。(符合人门观看世界的特点。)
2.将复杂的事情简单化。
3.将执行者变成指挥者(角色发生了改变)。

1.1.3面向对象的要求?

1.各司其职,各尽所能(一个类只做这个类该有的事情。)
2.弱耦合性(开发项目时,把强耦合变成弱耦合性。)
3.可重用性(代码的重用,功能的可重用)
4.可扩展性(补丁,把里面的内容扩展一下。)
5.高内聚性(一个对象独立完成一个功能的能力)

1.1.4面向对象的三大特征是什么?(重要)

封装、继承、多态,在封装前还应该有一个抽象。

1.2类和对象

1.2.1什么是类?

类是一组相关属性和行为的集合(泛化)里面是事物抽象出来的属性特征和行为特征,类是对象的模板。

1.2.2什么是对象?

对象:是一类事物的具体体现(特性化)。对象是类的一个实例(对象并不是找个女朋友),必然具备该类事物的属性和行为。(类是一类事物的共性,是人类主观认识的一种抽象,是对象的模板)

1.2.3类和对象的关系?

类是对一类事物的描述,是抽象的。对象是一类事物的实例,是具体的。类是对象的模板,对象是类的实例(实体)。

1.2.4.类的属性和行为。

属性(属性,全局变量,成员变量,实例变量):该事物的状态信息。(在类中通过成员变量来体现,类中方法外的变量)
行为:该事物能够做什么。(在类中通过成员方法来体现,和普通方法相比去掉static关键字)。

1.3局部变量和全局变量的区别

1.在类中的位置不同(成员变量:类中,方法外。局部变量:方法中或者方法声明上(形式参数))。
同一个范围内,不允许两个局部变量相同。
实例对象与局部变量冲突,局部优先。
2.作用范围不一样(成员变量:类中。局部变量:方法中。)
3.初始化值不一样(成员变量:有默认值,局部变量:没有默认值,必须先定义,赋值,然后使用。)
int a=0; String str = “”;/不会NullPointerException。String str = null;
4.在内存中的位置不一样(成员变量:堆内存。局部变量:栈内存。)
5.生命周期不同(成员变量:随着对象的创建而存在,随着对象的消失而消失。局部变量:随着方法的调用而存在,随着方法的调用完毕而消失)

二、类的定义和使用

2.1类的定义格式

修饰符 class 类名{
	//成员变量(属性)
	//成员方法
}

2.2对象的使用

创建对象格式:类名 对象名 = new 类名();//new后面是去调用类的构造方法。
创建对象的过程:new的过程(
1.递归地构造父类对象。
2…分配本类空间(堆中申请成员变量的空间) 。
3.初始化本类属性(基本数据类型初始化成各种零,引用类型初始化成null)。
4.调用本类的构造方法。
java中所有类的共同祖先是object类。

访问类中的成员格式:对象名.成员变量;对象名.成员方法();
赋值:对象名.成员变量=值;
成员变量在没有赋值的时候,会有一个默认值,这个默认值基本数据类型是各种各样的0,引用数据类型是null
整形:0/浮点数:0.0/字符:“\u0000”/布尔:false/引用数据类型:null

2.3对象的内存图

public class Student {
//属性  全局变量,成员变量,实例变量
	int sid;
	String name;
	String gender;
	String address;
	//无参构造方法
	public Student() {	
	}
	//全参构造方法
	public Student(int sid,String name,String gender,String address) {
		this.sid=sid;
		this.name=name;
		this.gender=gender;
		this.address=address;
	}	
	//行为  方法/函数
	public void eat() {
		System.out.println("去吃饭");
	}
	public void study() {
		System.out.println("去上电脑课");
	}
}

测试目录

public class TestStudent {
	public static void main(String[] args) {
		Student stu = new Student(1,"lisi","男","北京");
		stu.eat();
		stu.study();
	}
}

在这里插入图片描述
1.java被编译成字节码文件。
2.调用java虚拟机操作字节码文件,字节码文件中的方法被加载到方法区。
3.程序开始运行,main方法进入到栈内存中
4.创建对象,new会创建一个对象到堆内存中去,然后生成一个内存地址给栈内存,对象去到方法区将方法中的变量创建一份,并赋值上各种各样的0,然后将该对象中的方法引用(在栈内存中存储一个地址)。
5.然后main方法调用构造方法给该变量赋值,该值会保存到堆内存中,堆内存中的属性值发生改变。
6.main然后调用方法。先去栈内存中寻找对象的方法,然后栈内存中的方法根据内存地址调用方法区的该对象的方法。
7.main方法从栈内存中执行出来,就意味着方法的结束。
在这里插入图片描述
首先main方法在栈内存中加载着,然后开始创建对象,对象被加载到堆内存中,栈内存中保留着对象在堆内存中的地址,在堆内存中成员变量被赋默认值,成员方法被加载到方法区,内存中保留着方法区的地址,然后在栈内存中给在堆内存中的变量赋值,在栈内存中调用对象的方法。
在这里插入图片描述
两个对象的内存图。
在这里插入图片描述
多个对象指向相同的内存。

三、封装

3.1什么是封装?

定义:封装指的是一个对象的内部状态对外界是透明的,对象与对象之间只关心对方有什么方法而不关心属性。
封装使实现的改变(类中方法的改变)对架构(main方法调用时)的影响最小化。
面向对象的封装:封装指的是一个对象的内部状态对外界是透明的,对象与对象之间只关心对方有什么方法,而不关心属性。
工具类:只有方法,没有属性的类
jar包封装:多个类封装成一个可以被java虚拟机访问的jar包。
原则:封装使对象的属性尽可能的私有,根据需要配上相应的get/set方法,对象的方法尽可能公开。该隐藏的一定要隐藏,该公开的一定要公开。
方法公开的是声明而不是实现, 使方法实现的改变对架构的影响最小化。
该私有的私有,该公开的公开。
封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。
属性隐藏起来,若需要访问某个属性,提供公共方法对其访问。

3.2封装的作用?

加强了代码的安全性。

3.3修饰符

private(只能在本类中访问) —> [default(不能定义变量)]------>protected------>public
局部变量不能使用修饰符

修饰符本类同包不同包子类不同包
private可以不可以不可以不可以
[default]可以可以不可以不可以
protect可以可以可以不可以
pbulic可以可以可以可以

格式:private 数据类型 变量名;
既然被private修饰的变量只能在本类中访问,那么如何访问该类并修改该类呢?
可以在类中写该变量的setter和getter方法,对封装的变量进行修改。
声明变量时布尔类型一般前面加一个is,自动生成的get,set方法不会生产get和set需要手动添加。
javaBean:所有属性私有,具有无参构造方法,并且提供getter和setter方法操作成员变量的一种编写类的标准规范。

public class ClassName{  
    //成员变量
    //构造方法
    	//无参构造方法【必须】  
    	//有参构造方法【建议】  
    //成员方法    
    	//getXxx()
    	//setXxx()
}

private需要注意:

  1. private是一个权限修饰符,代表最小权限。
  2. 可以修饰成员变量和成员方法。
  3. 被private修饰后的成员变量和成员方法,只在本类中才能访问

四、构造方法。

定义:当一个对象被创建时候,构造方法用来初始化该对象,给对象的成员变量赋初始值。
所有的类都有构造方法,因为Java自动提供了一个无参数构造方法。
在对象的声明周期中,构造方法只被调用一次。
特点:
1.没有返回值,不用写void,但是能写return;。(如果有返回值并且类名和方法名一样,可以在主方法中调用该函数的方法。)
2.构造方法的名字与类名字相同。
3.构造方法不能显示(手动)调用。
4.如果不声明构造方法的话,系统自动提供一个无参数的构造方法。
5.如果你提供了构造方法,系统将不再提供构造方法。
6.在继承过程中构造方法不能被覆盖,不能被继承。
注意:养成手动添加无参构造
构造方法的定义格式

修饰符 类名(参数列表){ 
    // 方法体 
}

一个类中可以构造多少个构造方法?无数个。(这个是有多少种构造方法?一个有参的,一个无参的。)
在一个类中的某个构造方法中去调用另一个构造方法,并且这一句必须写在构造方法的第一句。this([参数列表])

构造方法

1.构造方法不能被继承
2.构造方法不能被子类覆盖(重写)。

this

this的含义?this代表所在类的当前对象的引用(地址值),即对象自己的引用。
this的使用格式:this.成员变量名;
this关键字:
this.属性 指向当前对象的属性。
this.方法() 调用当前对象的方法。
this([参数列表]) 在一个类中的某个构造方法中去调用另一个构造方法,并且这一句必须写在构造方法的第一句。

五、继承

5.1继承的定义:

多个类中存在相同的属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那一个类即可。(基于一个已存在的类构造一个新的类)
继承:就是子类继承父类的属性行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。
其中,多个类可以称为子类,单独那一个类称为父类超类(superclass)或者基类(Baseclass)
父类更通用(一般),子类更具体(特殊)。

5.2继承的特点:

子类自动拥有父类非私有的成员 --一般
子类也可以拥有自己的成员 --特殊

5.3继承的好处:

提高代码的复用性
类与类之间产生了关系,是多态的前提
继承的格式:
通过 extends 关键字,可以声明一个子类继承另外一个父类
class 父类{}
class 子类 extends 父类{}

5.5java继承的特点

java支持单继承,不支持多继承

//一个类只能有一个父类,不可以有多个父类。
class C extends A{}     //ok
class C extends AB...  //error

java支持多层继承(继承体系)

//一个父类可以有很多个子类
class A{}
class B extends A{}
class C extends B{}

5.6继承中的成员变量和成员方法。

成员变量(实例变量)
1.父子类的成员变量不同名的时候,访问的时候没有影响
父类的非私有成员变量继承到了子类。
2.父子类中出现了同名的非私有成员变量时,子类的成员变量** 覆盖 **了父类的成员变量,如果要访问父类的成员变量需要用super关键字,格式:super.父类的成员变量。

成员方法(实例方法)
1.父子类实例方法不同名,调用没有影响。(继承的特性。)
2.父子类实例方法同名,会出现方法的覆盖。
用到super.父类成员方法,表示调用父类的成员方法

方法的覆盖(重写、复写)(Override)的特点?(重载(Overload)继承(inheriteance))
1.一定是发生在父子类之间。
2.方法名字相同,参数列表相同。
3.返回值类型要相同(特例)
4.子类的访问修饰符要和父类的访问修饰符相同或者更宽。
在这里插入图片描述
5.子类的方法抛出的异常类型要和父类方法抛出的异常类型相同,或者子类抛出的异常类型是父类抛出的异常类型的子孙类。
在这里插入图片描述
注意:如果父子类之间有方法名字相同,参数列表不相同,这些方法构成重载关系,构造方法也可以重载。

super

super的特点。
super不能在静态方法中使用
super:代表父类的存储空间标识(可以理解为父亲的引用)。
this:代表当前对象的引用(谁调用就代表谁)
super.属性名字 //调用父类的非私有属性。
super.方法名字 //调用父类非私有方法。
super([参数])😕/在子类的构造方法中调用父类的构造方法,并且必须是子类构造方法中的第一行。
不允许在一个构造方法中既调用本类的构造方法,又调用父类的构造方法。
子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。
可以借助父类的构造方法构造子类的对象
public 子类名(父类全参数){
super(全参数类型)
}

public class TestSuper {
	public static void main(String[] args) {
		//借助了父类的构造方法构造了一个子类
		//过程
		//首先main在主内存中,执行到new在堆内存中有了Person类,和Teacher类
		//创建Teacher类时自动引用了父类的内容,并执行了父类的构造方法,最后
		//所有的这些方法生产一个16进制代码,最后赋值给变量。
		//子类一经创建就会在栈内存中拥有子类和父类的全部非私有属性和方法。
		Teacher tea = new Teacher("lisi",29,"男");
		tea.getName();
	}
}
class Person {
	String name;
	int age;
	String gender;
	public Person() {
		
	}
	public Person(String name,int age,String gender) {
		//条件1:在父类的构造方法内部设有this.name=name;
		this.name = name;
		this.age = age;
		this.gender = gender;
		
	}
	public void getName() {
		System.out.println(this.name);
	}
}
class Teacher extends Person{
	public Teacher(String name,int age,String gender) {
		//条件2,调用了父类的构造方法。
		super(name,age,gender);
		
	}
}

七.多态

7.1.什么是多态?

定义:同一个对象,在不同时刻表现出来的形态是不同的。(多种形态)(把子类对象当做父类对象来看待)
多态的意义:在需要使用一类对象的共性时,可以用多来屏蔽掉其子类中的差异。

7.2.多态的前提

要有继承或实现关系
要有方法的重写(没有方法的重写体现不出来多态)
要有父类引用指向子类对象

7.3.多态的格式?

父类(祖先类) 引用 = new 子类();

7.4.多类中的成员访问特点。

成员变量:编译看父类(ide会不会报错),运行看父类(输出的结果)。
成员变量没有多态(不考虑覆盖的情况),引用类型是谁,调用的就是谁的属性。
成员方法:编译看父类,运行看子类。
多态编译成员方法时,只能调用引用类型中存在的方法,运行时调用的对象是谁,调用的就是谁的方法(覆盖之后的方法)。

7.5.多态的好处

可以使程序编写的更简单,并有良好的扩展。
多态总共三种用法。


public class TestAnimal {
	public static void main(String[] args) {
		//多态的写法,把子类对象当做父类对象来看待。1
		Animal an =  new Cat();
		System.out.println(an);//Cat@15db9742
		System.out.println(an.age);//10
		//1.多态用在方法的返回值上面  2
		TestAnimal te = new TestAnimal();
		Animal aa = te.getAnimal(1);
		aa.eat();//Cat eat foot
		aa = te.getAnimal(2);
		aa.eat();//Dog eat foot
		//2.多态用在方法的参数上面。 3.
		Cat ca = new Cat();
		te.feedAnimal(ca);//Cat eat foot
}
	//1、多态用在方法的返回值上面
	public Animal getAnimal(int type) {
		if(type==1) {
			return new Cat();
		}else if(type==2) {
			return new Dog();
		}else {
			return null;
		}
	}
	//2.多态用在方法的参数上面。
	public void feedAnimal(Animal animal) {
		animal.eat();
	}
}

class Animal {
	public int age=10;
	public void eat() {
		System.out.println("Animal eat foot");
	}
}
class Cat extends Animal {
	public int age=20;
	public void eat() {
		System.out.println("Cat eat foot");
	}
}
class Dog extends Animal {
	public void eat() {
		System.out.println("Dog eat foot");
	}
}

6.多态中的转型(类型转换)

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做向下转型。
多态的类型转换。
向上转型
多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的(隐式的)。
父类类型 变量名 = new 子类类型(); 如:Animal a = new Cat();
向下转型
父类类型向子类类型向下转换的过程,这个过程是强制的。
一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。
子类类型 变量名 = (子类类型) 父类变量名; 如:Cat c =(Cat) a;

//类型转换
Animal ac = new Cat();
Animal a1 = new Animal();
//Cat ca = (Cat)aa;//aa后面是Animal证明aa还是Animal,不能强制类型转换。
Cat a2 = (Cat)ac;//ac后面是Cat证明ac是Cat,所以能强制类型转换

转型的异常 ,下面这段代可以通过编译,运行时却报出了ClassCastException类型转换异常!这是因为,明明创建了
Cat类型对象,运行时,当然不能转换成Dog对象的。这两个类型并没有任何继承关系,不符合类型转换的定义。
为了避免ClassCastException的发生,Java提供了instanceof关键字,给引用变量做类型的校验

 public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat
 
        // 向下转型  
        Dog d = (Dog)a;       
        d.watchHouse();        // 调用的是 Dog 的 watchHouse 【运行报错】    }  
}

类型转换之前要做一次判断,判断对象是不是某个类型所创建出来的对象。
//a instanceof b 判断a是不是根据b这个模板创建出来的。返回布尔值。

Animal ac = new Cat();
Animal a1 = new Animal();
//Cat ca = (Cat)aa;//aa后面是Animal证明aa还是Animal,不能强制类型转换。
//Cat a2 = (Cat)ac;//ac后面是Cat证明ac是Cat,所以能强制类型转换。
//类型转换之前要做一次判断,判断对象是不是某个类型所创建出来的对象。
Cat a2 = null;
if(aa instanceof Cat) {
	a2 = (Cat)ac;
}

八抽象类

8.1.概述

​ 父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类

注意:有抽象方法的类一定是抽象类。但是抽象类中不一定都是抽象方法,也可以全是具体方法。

abstract修饰符在修饰类时必须放在类名前,abstract修饰的类是抽象类,有抽象方法的类是抽象类,抽象类可以没有抽象方法。

8.2.什么是抽象方法:只有方法的声明,没有方法体的方法,就是抽象方法。
8.3.什么是抽象类:抽象方法所在的类必定是一个抽象类,(有抽象方法的类必须是抽象类, 抽象类可以没有抽象方法。:理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。)

8.4.格式:修饰符 abstract 返回值类型 方法名 (参数列表);

public abstract class Test {
	public abstract void run();
}

8.5.abstract的特点:

  • 1.abstract可以修饰类(必须放在类名前),方法,不能修饰属性。
  • 2.一个类要想继承自抽象类,必须实现抽象类中的所有方法,否则(不实现)这个类必须是抽象的(最终,必须有子类实现该父
    类的抽象方法,否则,从最初的父类到最终的子类都不能创建对象,失去意义。子类对父类抽象方法的完成实现,也叫做实现方法。)
    理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。
  • 3.抽象类不能实例化对象(不能创建抽象类的对象,只能创建其非抽象子类的对象。)
    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的实现,没有意义。
  • 4.抽象类可以有构造方法(供子类创建对象时,初始化父类成员使用的。),但是不能创建对象,也就是不能new 类名();
    理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
  • 5.抽象类可以声明引用,抽象类的引用可以指出子类的实例。
  • 6.有抽象类后,java中对象的创建过程不变。
  • 7.没有private abstract组合修饰的方法

九接口

9.1.接口的概述?
接口:接口是一种程序结构,是特殊的抽象类。接口主要是扩展功能的。是定义标准的。是一种引用类型,是方法的集合。(Java中的接口更多的体现在对行为的抽象!)接口的内部主要就是封装了方法(功能),包含抽象方法 (JDK7及以前) , 默认方法和静态方法(JDK8)私有方法(JDK9)。接口中的方法必须都是公开的抽象方法(public abstract),接口中的属性都是公开静态常量(public static final)。
默认方法:使用default关键字来修饰的方法,在接口中可以有默认实现
在接口的实现类中,可以有选择性的覆盖需要覆盖的方法。
静态方法:使用static修饰符来修饰,可以有自己的实现
接口中的静态方法和常量一般使用来写工具类的。
9.2 接口定义格式?
声明一个接口用 interface 关键字,接口也是一种类型,编译之后也有生成相应字节码,他的声明规范也要符合类型的定义(一个源文件中只能有一个public interface,接口名和源文件名相同,有public interface,就不能再写public class了)。接口中的属性可以不加修饰符,方法也不用加修饰符。

public interface 接口名 {}

9.3.接口的特点?

  • 1.接口不能创建对象,必须有实现类才能使用,类实现接口用implements表示.

  • 2.接口的实现类必须重写接口中的所有的抽象方法,要么该类是一个抽象类.
    public class 类名 implements 接口名{}

  • 3.一个类只能继承一个父类,同时实现多个接口。(一个类的直接父类是唯一的,但是一个类可以同时实现多个接口)(使用接口分出功能的主次,主要的功能用继承来实现(还存在),次要的功能用接口来实现(实现接口))
    class 类名 [extends 父类名] implements 接口名1,接口名2,接口名3… {
    // 重写接口中抽象方法【必须】如果抽象方法有重名的,只需要重写一次即可
    }

  • 4.接口没有构造方法。(接口主要是扩展功能的,而没有具体存在 。)

9.4.接口成员的特点?

  • 成员变量,只能是常量,默认修饰符:public static final
  • 成员方法,只能是抽象方法,默认修饰符:public abstract

9.5.类和接口的关系?

  • 类与类的关系:继承关系,只能单继承,但可以多层继承。
  • 类和接口的关系:实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口。
  • 接口与接口的关系:继承关系,可以单继承,也可以多继承。

9.6.抽象类和接口的区别?

  • 1.成员:
    抽象类:变量,常量;有构造方法;有抽象方法,也有非抽象方法
    接口:常量;抽象方法
  • 2.关系区别:
    类与类:继承,单继承
    类与接口:实现,可以单实现,也可以多实现
    接口与接口:继承,单继承,多继承
  • 3.设计理念区别:
    抽象类:为了继承而来,让子类强制重写父类中的抽象方法。
    接口:对行为抽象,主要是行为。

9.7接口的使用。

使用多态创建对象
接口的引用,指向子代的对象。
使用标准可以屏蔽不同实现类的实现差异。(调用不同的类中的方法体。)
p v A(FirstInterface fii){//多态用在方法的参数上
fii.print();
}
p s FistInterface getImpl(){//多态用在方法的返回值上。
return new FirstInterfaceImpl();
}
FirstInterface fii = new FirstINterFaceImpl();//多态的写法
FirstInterface fii2 = new FirstInterfaceImpl2();//多态的写法。
A(fii);
A(fii2);

接口回调?
接口使用者,接口实现者,接口
没有实现者:针对接口编程,只要有接口(标准),那么就可以敲代码。
接口回调:先有使用者,后有实现者,把接口实现者的对象传给接口的使用者,通过接口的实现者来调用接口中的方法,完成接
先有接口的定义,再有接口使用者,最后把接口的实现对象传入接口的使用者中,接口的使用者会通过接口来调用接口实现者的方法。口回调。
接口使用适配器的类来实现,然后再使用类来继承该适配类。

十、final关键字

可以修饰类,方法,成员变量,局部变量。

  • final修饰类(不变模式),是最终类,修饰的类不能有子类。
  • final修饰方法,该方法不能被子类覆盖(重写)。
  • final修饰成员变量(类中方法外),变量一旦赋值,不可改变。常量(直接赋值,别先声明后赋值。)
  • final修饰局部变量,变量值不能改变。(可以先声明后赋值。)

注意:final,不能用来修饰构造方法,在父类中如果有常量属性,在子类中使用常量属性时是不会进行父类的类加载。静态常量如果其值可以确定,就不会加载该类,如果不能确定则会加载该常量所在的类。
不变模式,对象一旦创建属性就不会改变。用final修饰属性,也用final修饰类(强不变模式),用final修饰属性(弱不变模式)。面试题:String类使用final修饰的(骡子),不能够有子类,被继承。

十一、static关键字

11.1 什么是static关键字?
用来修饰的成员变量和成员方法,被修饰的成员是属于类的,而不单单是属于某个对象的。
11.2 static的定义?
11.2.1 static定义变量:static 数据类型 变量名
使用 static关键字修饰的成员变量。
当 static 修饰成员变量时,该变量称为类变量。该类的每个对象都共享同一个类变量的值。
任何对象都可以更改该类变量的值,但也可以在不创建该类的对象的情况下对类变量进行操作。
11.3 static定义方法:修饰符 static 返回值类型 方法名 (参数列表){}
使用 static关键字修饰的成员方法,习惯称为静态方法。
当 static 修饰成员方法时,该方法称为类方法 。静态方法在声明中有 static ,建议使用类名来调用,而不需要 创建类的对象。调用方式非常简单。
用引用访问类成员,等同于拿引用的类型来访问类成员。
11.4:注意事项

  • 静态方法可以直接访问类变量和静态方法。
  • 静态方法不能直接访问普通成员变量或成员方法(可以通过组合方式访问)。反之,成员方法可以直接访问类变量或静态方法。
  • 静态方法中,不能使用this关键字。
  • 父子类之间:子类的静态方法覆盖父类的静态方法,没有多态;子类的非静态方法,覆盖父类的非静态方法(不能覆盖静态方法)。

11.5.静态代码块
static修饰初始代码块,这时这个初始代码块就叫做静态初始代码块,这个代码块只在类加载时被执行一次。可以用静态初始代码块初始化一个类。
动态初始代码块,写在类体中的“{}”,这个代码块是在生成对象的初始化属性时运行。这种代码块叫动态初始代码块。
定义在成员位置(类中方法外。),使用static修饰的代码块{}。
执行:随着类的加载而执行且执行一次,优先于main方法和构造方法的执行。
java中的main方法必须写成static的因为,在类加载时无法创建对象,因为静态方法可以不通过对象调用。所以在类的main方法。所在在类加载时就可以通过main方法入口来运行程序。
注意:组合方式,就是需要在方法中创建一个所需要的对象,并用这个对象来调用任意所需的该对象的内容,不会再受只能访问静态的约束。
11.5.1:调用格式
被static修饰的成员可以并且建议通过类名直接访问。虽然也可以通过对象名访问静态成员,原因即多个对象均属于一个类,共享使用同一个静态成员,但是不建议,会出现警告信息. 一般情况下用static关键字来写工具类.
// 访问类变量
类名.类变量名;
// 调用静态方法
类名.静态方法名(参数);
被static修饰的内容,是随着类的加载而加载的,且只加载一次。
存储于一块固定的内存区域(静态区(方法区中的一块)),所以,可以直接被类名调用。
它优先于对象存在,所以,可以被所有对象共享。
面试题。
什么是类加载?
类加载的过程,类本身也是保存在文件中(字节码文件保存着类的信息)的,java会通过I/O流把类的文件(字节码文件)读入JVM(java虚拟机),这个过程称为类的加载。JVM(java虚拟机)会通过类路径(CLASSPATH)来找字节码文件。
类变量,会在加载时自动初始化,初始化规则和实例变量相同。
注意:类中的实例变量是在创建对象时被初始化的,被static修饰的属性,也就是类变量,是在类加载时被创建并进行初始化,类加载的过程是进行一次。也就是类变量只会被创建一次。
什么时候发生类加载?
1.构造对象的时候(调用构造方法时)会发生类加载。
2.调用类的静态方法会发生类加载。
3.访问类中的静态属性会发生类加载。
4.构造子类对象,会先加载父类,再加载本类。
5.访问子类的静态方法,会先加载父类,再加载本类。
6.访问子类的类变量,会先加载父类,再加载本类。
7.访问子类中父类继承过来的静态方法,只会发生父类的加载。
8.访问类中的确定常量(static final),不会发生类加载。
什么时候不会发生类加载。
可以确定的常量的值不会发生类加载
static final double a = 2*10;//不会发生类加载。
static final double a = Math.random();//会发生类加载。

十二、内部类

掌握匿名内部类。
理解内部类的作用。
12.1.什么是内部类?、
将一个类A定义在另一个类B里面,里面的那个类A就被称为内部类,B称为外部类。
内部类还可以实现外部的接口。
内部类的分类?
12.2.成员内部类:类内,方法外。定义在成员位置。
创建内部类对象格式:外部类名.内部类名 变量名 = 内部类对象名.new 内部类();
编译的时候内部类前面有$符号,符号前面是外部类名。
特点:
1.内部类可以直接访问外部类的成员,包括私有成员。
2.外部类要想访问内部类的成员,必须创建内部类的对象,直接创建即可。
3.成员内部类不能有静态成员。

//成员内部类
public class Code1 {
    private int outNum = 10;
    //创建内部类对象,外部类名.内部类名 变量名 = 内部类对象名.new 内部类();
    Code1.Inner inner = new Code1().new Inner();
    //2.外部类要想访问内部类的成员,必须创建内部类的对象
    private int otherOutNum = inner.innerNum;
    //这是一个成员内部类
    private class Inner{
        private int innerNum = 20;
        //1.内部类可以直接访问外部类的成员,包括私有成员
        int otherNum = outNum;
        public void test(){
            System.out.println("内部类的内容");
        }
        //3.成员内部类不能有静态成员和抽象方法。
        //private static int a;
//        public static void sticTest(){}
//        private abstract void abstractTest();
    }
}

12.3.局部内部类。
将一个类定义在一个方法中,该类就称之为是局部内部类。
1.局部内部类不能使用public,private,protected这些修饰符。
2.局部内部类作用范围只能在定义它的方法体内部。
3.局部内部类可以访问外部类的属性(包括私有属性)
4.局部内部类可以访问定义它的方法体内的局部常量(final,final可以省略)。
5.jdk1.7之前final必须写,1.8开始可以不写final但是本质上局部内部类访问的局部变量还是final修饰的。
6.类外不能直接访问局部内部类,在方法中才能调用局部内部类。印证了第二点。

public class Code2 {
    private int outNum = 10;
    public void test(){
        //5.jdk1.7之前final必须写,1.8开始可以不写final但是本质上局部内部类访问的局部变量还是final修饰的。
        final int testNum = 20;
        //1.局部内部类不能使用public,private,protected这些修饰符。
        //2.局部内部类作用范围只能在定义它的方法体内部。
        class Inner{
            //3.局部内部类可以访问外部类的属性(包括私有属性)
            int innerNum = outNum;
            //4.局部内部类可以访问定义它的方法体内的局部常量(final,final可以省略)
            int numTest = testNum;

            private void innerTest(){
                System.out.println("局部内部类的方法。");
            }
        }
        //创建局部内部类
        Inner inner = new Inner();
        inner.innerTest();//调用方法
    }
}

12.4匿名内部类。
内部类的简化写法,它的本质是一个带具体实现的父类或者父接口的子类写法。
编译后类名$1/2.class
使用匿名内部类的前提:匿名内部类必须继承一个父类,或者实现一个父接口。

public class Outer {
    public void test() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello World!");
            }
        }).start();
    }
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.test();
    }
}

12.5静态成员内部类。
1.定义在类内部,所有方法之外,用static修饰
2.静态内部类可以访问外部类静态成员。
3.创建对象?
外部类.内部类 变量名 = new 外部类.内部类();
从创建的方式可以看出:该内部类就是把静态内部类看成是一个顶层类。
4.静态内部类:不可以使用private修饰,修饰后不能访问,就失去了意义。

//静态内部类
public class Code3 {
    static int num = 10;
    int twoNum = 11;
    //3.创建对象,外部类.内部类  变量名 = new 外部类.内部类();
    Code3.Inner inner = new Code3.Inner();
    //1.定义在类内部,所有方法之外,用static修饰
  static class Inner{
    //2.静态内部类可以访问外部类静态成员。
        int innerNum = num;
//        int innerNum2 = twoNum;//这个不对。

      public void  print(){
          System.out.println("静态内部类");
      }
  }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值