黑马程序员——Java面向对象(this关键字、静态、单例设计模式、继承)

时间:2021-02-23 00:39:29

this关键字

看上去,是用于区*部变量和成员变量同名的情况。this为什么可以解决这个问题?this到底代表的是什么呢?
this代表本类的对象,到底代表哪一个呢?this代表它所在函数所属对象的引用。简单的说,哪个对象在调用this所在的函数,this就代表哪个对象。
this的应用:当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。换句话说,但凡是本类功能内部要用到本类对象时都是用this表示。构造函数间调用只能用this语句。this语句只能定义在构造函数内的第一行。 

需求:给人定义一个用于比较年龄是否相同的功能,也就是是否为同龄人。代码示例:

class  Person
{
private String name;
private int age;

Person(int age)
{
this.age = age;
}
public boolean compare(Person p)
{
return this.age == p.age;
}
}
class PersonThis
{
public static void main(String[] args)
{
Person p1 = new Person(22);
Person p2 = new Person(25);
boolean b = p1.compare(p2);
System.out.println(b);
}
}

static关键字

静态的意思。用于修饰成员(成员变量和成员函数)。

被修饰后的成员具备以下特点:

1.随着类的加载而加载。也就是说,静态会随着类的消失而消失,说明它的生命周期最长;

2.优先于对象存在。明确一点:静态是先存在对象是后存在的;

3.被所有对象所共享;

4.可以直接被类名调用;

使用注意:

1.静态方法只能访问静态成员;非静态方法既可以访问静态也可以访问非静态。

2.静态方法中不可以写this,super关键字。因为静态优先于非静态存在,所以静态方法中不可以出现this。

3.主函数是静态的。 
当成员被静态修饰后就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用。 类名.静态成员。

类变量和实例变量的区别:

1.存放位置不同:类变量随着类的加载而存在于方法区中。实例变量随着对象的建立而存在于堆内存中。

2.生命周期不同:类变量生命周期最长,随着类的消失而消失。实例变量生命周期随着对象的消失而消失。

静态有利有弊:

利处:对对象的共享数据进行单独空间的存储,可以节省空间。没有必要每一个对象都存储一份。可以直接被类名调用。弊端:生命周期过长,占用内存空间。访问出现局限性,静态虽好却只能访问静态的。

静态演示代码:

class Person 
{
String name; //成员变量或实例变量。
static String country = "CN"; //静态的成员变量或类变量

public static void show()
{
System.out.print(name+":::"+country);
}
}

class StaticDemo
{
public static void main(String[] args)
{
Person p = new Person();
p.name ="lisi";
Person.show();
System.out.println(Person.country);
}
}

main 函数

主函数是一个特殊的函数。作为程序的入口可以被虚拟机所调用。public :代表着该函数的访问权限是最大的。 static :代表主函数随着类的加载就已经存在了。void :代表主函数没有具体的返回值。main :不是关键字,却是一个特殊的单词,可以被jvm识别。(String[] args):是函数的参数,参数类型是一个数组,该数组中的元素是字符串,字符串类型的数组。主函数的格式是固定的,可以被jvm识别。jvm在调用主函数时传入的是new String[0]  。

class MainDemo 
{
public static void main(String[] args)//new String[]
{
String[] arr = {"hah","hhe","heihei","xixi","hiahia"};

MainTest.main(arr);
}
}

什么时候使用静态?要从两方面下手,因为静态修饰的内容有成员变量和成员函数。
1.什么时候定义静态变量(类变量)呢?当对象中出现共享数据的时候,该数据就需要被静态所修饰。对象中的特有数据要定义成非静态变量(实例变量)存在于堆内存中。
2.什么时候定义静态函数呢?如果定义了一个功能是非静态的,但是这个功能内部没有访问到非静态数据(对象的特有数据)的时候,那么该功能可以定义成静态的。

一个类中会默认有一个空参数的构造函数,这个默认的构造函数的权限和所属类的权限一致。如果类被public修饰,那么默认的构造函数也带public修饰符。如果类没有被public修饰,那么默认的构造函数也没有被public修饰。也就是说,默认的构造函数的权限是随着类权限的变化而变化的。
将ArrayTool.class文件发送给其他人,其他人只要将该文件设置到classpath路径下就可以使用该工具类。但是,该类中到底定义了多少个方法对方并不清楚。因为该类并没有使用说明书。开始制作程序的说明文档,java的说明书通过文档注释来完成。制作程序说明书的类必须是被public修饰类。在DOS命令行里输入:javadoc -d 存放的位置 -author -version ArrayTool.java  命令进行编译程序说明文档。

静态代码块:格式:static{大括号里面是静态代码块里的执行语句}  特点:随着类的加载而执行,只执行一次且优先于主函数执行。 作用:用于给类进行初始化。   静态代码块只能访问静态成员,不能访问非静态成员。

静态代码块演示:

class StaticCode
{
int num = 9;
StaticCode()
{
System.out.println("b");
}

static
{
System.out.println("a");
}
{
System.out.println("c"+this.num);
}

StaticCode(int x)
{
System.out.println("d");
}
public static void show()
{
System.out.println("show run");
}
}

class StaticCodeDemo
{
static
{
System.out.println("b");
}
public static void main(String[] args)
{
new StaticCode(4);
}
}

对象的初始化过程:

Person p = new Person("zhangsan",10); 该句代码一执行都做了哪些事情呢 ?
1.因为new用到了Person.class,所以会先找到Person.class文件并加载到内存中。
2.执行该类中的static代码块,如果有的话给Person.class类进行初始化。  3.在堆内存中开辟空间,分配内存地址。
4.在堆内存中建立对象的特有属性并进行默认初始化。  5.对属性进行显示初始化。  6.对对象进行构造代码块初始化。
7.对对象进行对应的构造函数初始化。  8.将内存地址赋给栈内存中的p变量。

设计模式:解决某一类问题最行之有效的方法。 java中有23种设计模式。

单例设计模式:

解决一个类在内存只存在一个对象。  思想:要保证对象唯一。

单例设计模式有两种体现:饿汉式和懒汉式。定义单例时建议使用饿汉式。

1.为了避免其他程序过多建立该类对象,先禁止其他程序建立该类对象。

2.为了让其他程序可以访问到该类对象,只好在本类中自定义一个对象。

3.为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。

步骤:这三步怎么用代码体现呢?

1.将构造函数私有化。

2.在类中创建一个私有并静态本类对象。

3.提供一个公有并静态方法可以获取到该对象。

饿汉式单例设计模式:

class Single
{
private Single(){}
private static Single s = new Single();
public static Single getInstance()
{
return s;
}
}
懒汉式单例设计模式:
class Single{private Single(){}   private static Single s =null;  //先不创建本类对象。public static Single getInstance()  //调用方法的时候创建本类对象。{if(s==null){synchronized(Single.class){if (s==null)s = new Single();}}return s;}}
懒汉式单例设计模式特点是实例的延迟加载,多线程访问时会出现安全问题,可以加同步解决,
用同步代码块和同步函数都可以解决,但稍微低效。用双重判断的形式能解决低效问题。
加同步使用的锁是该类所属的字节码文件对象。

对于事物该怎么描述还怎么描述,当需要将该事物的对象保证在内存中唯一时,就将以上的三步加上即可。

继承:

好处:1.提高了代码的复用性。 2.让类与类之间产生关系,类之间有了关系才有了之后的多态。

extends 关键字,extends的作用是将两个类联系起来,使两个类之间有关系。

注意:类与类之间有所属关系才可以继承,不要为了获取其他类的功能简化代码而继承。java只支持单继承,不支持多继承。因为多继承容易带来安全隐患:当多个父类中定义了多个功能,但功能内容不同时,子类对象不确定要运行哪一个。

如何判断两个类之间是否有所属关系呢?如果搞不清楚那就先继承一下,看看子类是否全都具备父类中的内容,如果父类中有的内容子类中没有,那么两个类之间就不应该有继承。
java当中支持多层继承(继承体系)。那如何使用一个继承体系中的功能呢?
想要使用体系先查阅体系中父类的描述,因为父类中定义的是该体系*性的功能。通过了解共性功能就可以知道该体系的基本功能,这个体系就可以基本使用了。那么在具体调用时为什么要创建最子类的对象呢?1.因为有可能父类不能创建对象。2.创建子类对象可以使用更多的功能,包括基本的也包括特有的

简单一句话,查阅父类功能,创建子类对象使用功能。

继承代码示例:

class Person
{
String name;
int age;
}
class Student extends Person
{
void study()
{
System.out.println("good study");
}
}
class Worker extends Person
{
void work()
{
System.out.println("good work");
}
}
class ExtendsDemo
{
public static void main(String[] args)
{
Student s = new Student();
s.name = "zhagnsan";
}
}