1:成员变量和局部变量
(1)在类中的位置不同
成员变量:类中方法外
局部变量:方法定义中或者方法声明上
(2)在内存中的位置不同
成员变量:在堆中
局部变量:在栈中
(3)生命周期不同
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
(4)初始化值不同
成员变量:有默认值
局部变量:没有默认值,必须定义,赋值,然后才能使用
2:匿名对象
(1)没有名字的对象
(2)应用场景
A:调用方法,仅仅只调用一次的时候。
b:可以作为实际参数传递。
public class Student {
public void show() {
System.out.println("show 方法");
}
}
public class VariableTest {
public static void main(String[] args) {
Student stu=new Student();
stu.show();
//匿名对象调用方法,匿名对象对象调用完成后就是垃圾,可以被垃圾回收器回收
new Student().show();
}
}
3:private关键字
(1)私有的意义,可以修饰成员变量和成员方法
(2)特点:
被private修饰的后的成员只能在本类中被访问
4:this关键字
(1)代表当前类的引用对象
记住:哪个对象调用方法,该方法内部的this就代表那个对象
(2)this的应用场景:
A:解决了局部变量隐藏成员变量的问题
public class Student {
private String name;
private int age;
//默认的无参构造方法
public Student() {
}
//自己定义的有参构造方法
public Student(String name,int age) {
this.name = name;
this.age = 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;
}
}
this 关键字内存图解
5:构造方法
(1)作用:用于对对象的数据进行初始化
(2)格式:
A:方法名和类名相同
B:没有返回值类型,连void都不能有
C:没有返回值
思考题:构造方法中可不可以有return语句呢?
可以。而是我们写成这个样子就OK了:return;
其实,在任何的void类型的方法的最后都可以写上:return;
(3)构造方法的注意事项
A:如果我们没写构造方法,系统将提供一个默认的无参构造方法
B:如果我们给出了构造方法,系统将不再提供默认构造方法
示例:代码:Student s = new Student();做了哪些事情?
(1)把Student.class文件加载到内存
(2)在栈内存为s开辟空间
(3)在堆内存为学生对象申请空间
(4)给学生的成员变量进行默认初始化。null,0
(5)给学生的成员变量进行显示初始化。林青霞,27
(6)通过构造方法给成员变量进行初始化。刘意,30
(7)对象构造完毕,把地址赋值给s变量
6:static关键字
(1)静态的意思。可以修饰成员变量和成员方法。
(2)静态的特点:
A:随着类的加载而加载
B:优先于对象存在
C:被类的所有对象共享
D:可以通过类名调用
既可以通过对象名调用,也可以通过类名调用。
(3)静态的内存图
静态的内容在方法区的静态区
(4)静态的注意事项;
A:在静态方法中没有this对象
B:静态只能访问静态的成员变量和成员方法
/*
static关键字注意事项
A:在静态方法中是没有this关键字的
静态是随着类的加载而加载,this是随着对象的创建而存在。
静态比对象先存在。
B:静态方法只能访问静态的成员变量和静态的成员方法
静态方法:
成员变量:只能访问静态变量
成员方法:只能访问静态成员方法
非静态方法:
成员变量:可以是静态的,也可以是非静态的
成员方法:可是是静态的成员方法,也可以是非静态的成员方法。
*/
public class Teacher {
public int num=10;
public static int num2=20;
public void show() {
System.out.println(num);//隐含表示访问的是成员变量
System.out.println(this.num);//明确表示访问的是成员变量
System.out.println(num2);
function();
function1();
}
public static void method() {
// Cannot make a static reference to the non-static field num
// 无法从静态上下文中引用非静态 变量 num
//System.out.println(num);
System.out.println(num2);
// Cannot make a static reference to the non-static method function() from the type Teacher
// 无法从静态上下文中引用非静态 方法 function()
//function();
function1();
}
public void function() {}
public static void function1() {}
}
(5)静态变量和成员变量的区别
A:所属不同
静态变量:属于类,类变量
成员变量:属于对象,对象变量,实例变量
B:内存位置不同
静态变量:方法区的静态区
成员变量:堆内存
C:生命周期不同
静态变量:静态变量是随着类的加载而加载,随着类的消失而消失
成员变量:成员变量是随着对象的创建而存在,随着对象的消失而消失
D:调用不同
静态变量:可以通过对象名调用,也可以通过类名调用
成员变量:只能通过对象名调用
7:代码块
(1)用{}括起来的代码。根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程讲解)。
(2)分类:
A:局部代码块
在方法中出现 ,用于限定变量的生命周期,及早释放,提高内存利用率。
B:构造代码块
在类中方法外出现,把多个构造方法中相同的代码可以放到这里,每个构造方法执行前,首先执行构造代码块。
C:静态代码块
在类中方法外出现,并加上static修饰,对类的数据进行初始化,在类加载时就会执行,仅仅只执行一次。
(3)静态代码块,构造代码块,构造方法的顺序问题?
静态代码块 > 构造代码块 > 构造方法
示例:
/*
代码块:在Java中,使用{}括起来的代码被称为代码块。
根据其位置和声明的不同,可以分为
局部代码块:局部位置,用于限定变量的生命周期。
构造代码块:在类中的成员位置,用{}括起来的代码。每次调用构造方法执行前,都会先执行构造代码块。
作用:可以把多个构造方法中的共同代码放到一起,对对象进行初始化。
静态代码块:在类中的成员位置,用{}括起来的代码,只不过它用static修饰了。
作用:一般是对类进行初始化。
*/
class Code {
static {
int a = 1000;
System.out.println(a);
}
//构造代码块
{
int x = 100;
System.out.println(x);
}
//构造方法
public Code(){
System.out.println("code");
}
//构造方法
public Code(int a){
System.out.println("code1");
}
//构造代码块
{
int y = 200;
System.out.println(y);
}
//静态代码块
static {
int b = 2000;
System.out.println(b);
}
}
public class CodeTest {
public static void main(String[] args) {
//局部代码块
{
int x = 10;
System.out.println(x);
}
//找不到符号
//System.out.println(x);
{
int y = 20;
System.out.println(y);
}
System.out.println("---------------");
Code c = new Code();
System.out.println("---------------");
Code c2 = new Code();
System.out.println("---------------");
Code c3 = new Code(1);
}
}
打印结果:
10
20
---------------
1000
2000
100
200
code
---------------
100
200
code
---------------
100
200
code1
8:super 关键字
(1)this和super的区别
this代表本类对应的引用。
super代表父类存储空间的标识(可以理解为父类引用)
(2)用法
访问成员变量
this.成员变量 super.成员变量
访问构造方法
this(…) super(…)
访问成员方法
this.成员方法() super.成员方法()
9:继承
(1)把多个类中相同的成员给提取出来定义到一个独立的类中。然后让这多个类和该独立的类产生一个关系,
这多个类就具备了这些内容。这个关系叫继承。
(2)Java中如何表示继承呢?格式是什么呢?
A:用关键字extends表示
B:格式:
class 子类名 extends 父类名 {}
(3)继承的好处:
A:提高了代码的复用性
B:提高了代码的维护性
C:让类与类产生了一个关系,是多态的前提
(4)继承的弊端:
A:让类的耦合性增强。这样某个类的改变,就会影响其他和该类相关的类。
开发的 原则:低耦合,高内聚。
耦合:类与类的关系
内聚:自己完成某件事情的能力
B:打破了封装性
(5)Java中继承的特点
A:Java中类只支持单继承
B:Java中可以多层(重)继承(继承体系)
(6)继承的注意事项:
A:子类不能继承父类的私有成员(成员变量和成员方法)
B:子类不能继承父类的构造方法,但是可以通过super去访问。
(7)Java继承中的成员关系
A:成员变量
a:子类的成员变量名称和父类中的成员变量名称不一样
class Father{
public int num=10;
}
class Son extends Father{
public int num1=20;// 10,20
public void show() {
System.out.println(num);
System.out.println(num1);
}
}
public class ExtendsTest {
public static void main(String[] args) {
Son s=new Son();
s.show();
}
}
b:子类的成员变量名称和父类中的成员变量名称一样,怎么访问?
子类的方法访问变量的查找顺序:
在子类方法的局部范围找,有就使用。
在子类的成员范围找,有就使用。
在父类的成员范围找,有就使用。
找不到,就报错。
class Father{
public int num=10;//10,30
}
class Son extends Father{
public int num=20;//20,30
public int num1=30;
public void show() {
int num=40;// 40,30
System.out.println(num);
System.out.println(num1);
System.out.println(this.num);//20
System.out.println(super.num);//10
}
}
public class ExtendsTest {
public static void main(String[] args) {
Son s=new Son();
s.show();
}
}
B:构造方法
a:子类的构造方法默认会去访问父类的无参构造方法
是为了子类访问父类数据的初始化
b:父类中如果没有无参构造方法,怎么办?
子类通过super去明确调用带参构造
子类通过this调用本身的其他构造,但是一定会有一个去访问了父类的构造
让父类提供无参构造
/*
如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢?
报错。
如何解决呢?
A:在父类中加一个无参构造方法
B:通过使用super关键字去显示的调用父类的带参构造方法
C:子类通过this去调用本类的其他构造方法
子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化。
注意事项:
this(...)或者super(...)必须出现在第一条语句上。
如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化,所以必须放在第一条语句上。
*/
class Father{
public Father() {
System.out.println("Father的无参构造");
}
public Father(String name) {
System.out.println("Father的带参构造");
}
}
class Father2{
public Father2(String name) {
System.out.println("Father2的带参构造");
}
}
class Son extends Father{
public Son() {
//构造方法的第一条默认语句,可以省略不写
//super();
System.out.println("Son的无参构造");
}
public Son(String name) {
//构造方法的第一条默认语句,可以省略不写
//super();
System.out.println("Son的带参构造");
}
}
class Daughter extends Father2{
//mplicit super constructor Father2() is undefined. Must explicitly invoke another constructor
//父类没有无参构造函数
public Daughter() {
//构造方法的第一条默认语句,可以省略不写
super("任意给");
System.out.println("Daughter的无参构造");
}
//mplicit super constructor Father2() is undefined. Must explicitly invoke another constructor
//父类没有无参构造函数
public Daughter(String name) {
//构造方法的第一条默认语句,可以省略不写
//super("任意给");
this();
System.out.println("Daughter的带参构造");
}
}
public class ExtendsTest {
public static void main(String[] args) {
//Son s=new Son();// Father的无参构造 Son的无参构造
//Son s1=new Son("lwj");//Father的无参构造 Son的带参构造
//Daughter d=new Daughter();//Father2的带参构造 Daughter的无参构造
//Daughter d1=new Daughter("lwj");//Father2的带参构造 Daughter的带参构造
Daughter d2=new Daughter("sss");//Father2的带参构造 Daughter的无参构造 Daughter的带参构造
}
}
用例:根据程序写结果
1 子父类的构造执行过程示例
class Fu{
static {
// 1
System.out.println("静态代码块Fu");
}
{
//3
System.out.println("构造代码块Fu");
}
public Fu() {
//4
System.out.println("构造方法Fu");
}
}
class Zi extends Fu{
static {
//2
System.out.println("静态代码块Zi");
}
{
//5
System.out.println("构造代码块Zi");
}
public Zi() {
//6
System.out.println("构造方法Zi");
}
}
public class ExtendsTestTwo {
public static void main(String[] args) {
/* 静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi*/
Zi z=new Zi();
}
}
2 分层初始化示例
/*
A:成员变量的问题
int x = 10; //成员变量是基本类型
Student s = new Student(); //成员变量是引用类型
B:一个类的初始化过程
成员变量的初始化
默认初始化
显示初始化
构造方法初始化
C:子父类的初始化(分层初始化)
先进行父类初始化,然后进行子类初始化。
问题:
虽然子类中构造方法默认有一个super()
初始化的时候,不是按照那个顺序进行的。
而是按照分层初始化进行的。
它仅仅表示要先初始化父类数据,再初始化子类数据。
*/
class X{
Y b=new Y();
X(){
//2
System.out.println("X");
}
}
class Y{
Y(){
//1//3
System.out.println("Y");
}
}
public class ExtendsTestThree extends X {
Y y=new Y();
ExtendsTestThree(){
//4
System.out.println("ExtendsTestThree");
}
public static void main(String[] args) {
ExtendsTestThree ett=new ExtendsTestThree();//YXYExtendsTestThree
}
}
C:成员方法
a:子类的成员方法和父类中的成员方法名称不一样
b:子类的成员方法和父类中的成员方法名称一样,怎么访问?
通过子类对象访问一个方法的查找顺序:
在子类中找,有就使用
在父类中找,有就使用
找不到,就报错
9:方法重写
子类中出现了和父类中一模一样的方法声明,也称为方法覆盖,方法复写。
/*
方法重写的注意事项
A:父类中私有方法不能被重写
因为父类私有方法子类根本就无法继承
B:子类重写父类方法时,访问权限不能更低
最好就一致
C:父类静态方法,子类也必须通过静态方法进行重写
子类重写父类方法的时候,最好声明一模一样。
*/
class Father {
//private void show() {}
/*
public void show() {
System.out.println("show Father");
}
*/
void show() {
System.out.println("show Father");
}
/*
public static void method() {
}
*/
public void method() {
}
}
class Son extends Father {
//private void show() {}
/*
public void show() {
System.out.println("show Son");
}
*/
public void show() {
System.out.println("show Son");
}
public static void method() {
}
/*
public void method() {
}
*/
}
class ExtendsDemo10 {
public static void main(String[] args) {
Son s = new Son();
s.show();
}
}