Java学习笔记-单例模式等

该博文是传智播客Java基础视频的学习笔记仅为个人学习笔记,谢谢             

有些类当中,方法都是静态的,不需要创建对象,所以将构造函数私有化。

javadoc的用法:class 前边必须加上public,加上public之后,文件名和类名必须一致,文档能提取出来的只有共有的方法,也只能提取/** */注释的内容。

单例模式:私有化构造函数,通过new在本类中创建一个本类对象,定义一个公有方法,将创建的对象返回
继承:提高代码复用性,让类与类之间之间产生关系,多态产生的前提,Java中支持单继承,不直接支持多继承,但对c++中的多继承机制进行了改良。通过多实现的方式来体现。Java中支持多重继承,如:A extends B , B extends C ... ...,所以,要使用一个继承体系时,查看该体系的顶层类,了解基本功能,然后,创建最底层的子类对象,去使用功能 。
当本类的成员和局部变量同名,用this区分。当子父类中的成员变量同名时用super区分父类
子父类中成员变量的特点:
public class ExtendsDemo {
	public static void main(String[] args) {
		Zi z = new Zi();
		z.show();
	}
}
class Fu{
	int num = 5; 
	// 如果将该处的num设为private,
	// 则下边的super.num会提示The field Fu.num is not visible 
	// 即,子类不能直接访问父类中的私有成员
}
class Zi extends Fu{
	int num = 4;
	void show(){
		System.out.println(this.num+"..."+super.num);// 4...5  
	}
}

子父类中成员函数的特点--覆盖(也称重写、覆写,override):子父类中出现一模一样的情况,会执行子类的函数。重载是overload
覆盖注意事项:子类方法覆盖父类方法时,子类权限必须要大于等于父类的权限,否则会提示子类中的 方法无法覆盖父类中的方法(Cannot reduce the visibility of the inherited method from Fu)。
如果父类中的方法为private,那么就谈不上覆盖了,覆盖指的是,父类有一个方法可以用,但是子类不用,而是自己写一个出来把父类的方法覆盖掉,如果父类的某个方法为private,那么,虽然子类中定义了相同的方法不会出错,但只能叫做子类自己定义一个方法来用
静态只能覆盖静态,也只能被静态覆盖。

什么时候使用覆盖操作?
当对一个类进行子类扩展,子类需要保留父类的功能声明,但是要定义子类中该功能的特有内容时,就可以使用覆盖操作完成

子父类中构造函数的特点:
在子类所有的构造函数中,如果不显示调用父类构造函数,第一行都有一个默认的隐式语句,super();调用父类中空参数的构造函数

public class ExtendsDemo {
	public static void main(String[] args) {
		Zi z1 = new Zi();// 执行结果是 fu zi
		Zi z2 = new Zi(3);// 执行结果是 fu zi3
	}
}
class Fu{
	Fu(){
		// 如果将该构造函数改为下列构造函数,则需在zi()函数第一行显示调用super(int),
		// 否则会报错,因为,定义了有参构造函数,默认构造函数就没有了
		// zi()函数第一行中却有默认的super()
		System.out.println("fu");
	}
//	Fu(int x){
//		System.out.println("fu"+x);
//	}
}
class Zi extends Fu{
	Zi(){
		System.out.println("zi");
	}
	Zi(int x){
        //该处也是默认的调用super()
		System.out.println("zi"+x);
	}
}

因为子类继承了父类的内容,而父类会在构造函数中进行初始化,所以子类在使用父类的内容时,应该走父类的构造函数进行相同的初始化操作,即在子类的构造函数中默认加入了super()语句。
如果父类中定义了非空参数的构造函数,则子类构造函数中必须要在第一行用super语句明确调用父类中的某个构造函数。
如果子类构造函数中使用了this调用了本类的构造函数,那么super就没有了,因为this和super语句都只能放在函数中的第一行,但是子类中一定有一个构造函数调用父类的构造函数。


子类成员变量的初始化问题:
子类中通过super初始化父类的内容时,子类成员变量只是默认初始化,比如int类型的成员变量值为0,并未显示初始化,等super()父类初始化完毕后,才进行子类成员变量的显示初始化。

public class InitializationDemo {
	public static void main(String[] args) {
		Zi z = new Zi();  // zi...show...0
		z.show();  // zi...show...8
	}
}
class Fu{
	int num = 3;
	Fu(){
		show();
	}
	void show(){
		System.out.println("fu...show...");
	}
}
class Zi extends Fu{
	int num = 8;
	Zi(){
		super(); // 隐式的super()语句
		System.out.println("zi...ini..."+num);
		//此处super()语句执行完,父类的初始化完成,开始子类的成员变量的显示初始化
		//所以结果为zi...ini...8
	}
	void show(){
		System.out.println("zi...show..."+num);
	}
}

一个对象的实例化过程:
Person p = new Person();
1、JVM会读取指定路径下的Person.class文件,并加载进内存,同时会加载Person的父类(假设Person有父类)
2、在堆内存中开辟空间,分配地址
3、在堆内存的对象空间中对对象的属性进行默认初始化
4、调用对应的构造函数进行初始化
5、在构造函数中,第一行会先调用父类的构造函数进行初始化
6、父类初始化完毕后,再对本类的属性进行显示初始化
7、再进行本类构造函数的特定初始化
8、所有初始化完毕后,将地址赋给引用变量 p


final关键字:
final可以修饰类、方法和变量
final修饰的类不可以被继承
final修饰的方法不可以被覆盖
final修饰的变量是一个常量,只能被赋值一次
内部类只能访问被final修饰的局部变量

应用场景:
1、封装被打破是继承的弊端之一,可以考虑使用final修饰类避免,如:final class Fu
2、如果Fu类中,只有一部分方法不能被覆盖,则只需用final修饰不能被覆盖的方法
3、如果一个变量是固定值,就可以用final修饰这个变量为一个常量,名称规范:所有字母大写,单词间用下划线连接,常量只能赋值一次
final int x;语句会报错,The blank final field x may not have been initialized,因为final修饰的变量需要显示初始化

 

抽象:

抽象类特点:
1、方法只有声明没有具体实现,该方法就是抽象方法,需要被abstract修饰,如abstract void show();
抽象方法必须定义在抽象类中,抽象类也是用abstract修饰 abstract class Demo{}
2、抽象类不可以被实例化
3、抽象类的子类必须覆盖所有抽象方法之后,才能创建对象,否则这个子类还是一个抽象类


抽象类中也有构造函数,用于给子类对象进行初始化
抽象类中也可以不定义抽象方法,目的就是不让该类创建对象,但是这种情况很少见,AWT的适配器对象就是这种类,通常这个类中的方法有方法体,但是却没有内容
abstract关键字不可以和private、static、final进行组合


接口:当一个抽象类中的方法都是抽象的时候,可以将这个类用另一种形式来体现。
接口的出现将Java中的多继承通过另一种方式体现出来,即多实现
格式:interface{}
接口中的成员修饰符是固定的,接口中的成员都是public的
成员常量:public static final
成员函数:public abstract
由于接口中的修饰符格式是固定的,所以,接口中成员的修饰符public、 static 、final 和abstract都可以省略


一个类在继承某个类的同时,还能实现多个接口,接口与接口之间是继承关系,而且接口之间可以多继承,原因就是没有方法体,不会出现执行内容的不确定性。



多态:
在代码中的体现就是,父类或者接口的引用指向子类对象,提高代码的扩展性
多态的前提:
1、必须存在继承或实现关系
2、需要存在覆盖

多态使用过程中,涉及 instanceof 的使用,instanceof 只能用于引用数据类型的判断


多态的特点:
成员函数:编译时,要看引用变量所属的类中是否有所调用的成员,有则编译通过,没有,则编译失败。运行时,要查看对象所属的类
成员变量:编译时,要看引用变量所属的类中是否有所调用的成员,有则编译通过,没有,则编译失败。运行时,只看引用变量所属的类
静态函数:编译和运行都参考引用变量所属的类


内部类:

内部类可以直接访问外部类中的成员,包括私有成员
外部类要访问内部类中的成员,必须要建立内部类对象
内部类可以被成员修饰符所修饰
内部类的使用场景:

假设Inner为Outer的内部类,则在其他类中创建Inner对象的写法为:
Outer.Inner in = new Outer().new Inner();
如果内部类是静态的,相当于一个外部类
Outer.Inner in = new Outer.Inner();
如果内部类是静态的,内部类的成员也是静态的,则直接使用:
Outer.Inner.show();
如果一个内部类中有了静态成员,该内部类必须用静态修饰

public class InnerClassDemo {
	public static void main(String[] args) {
		new Outer().method();
	}
}
class Outer{
	int num = 3;
	class Inner{
		int num = 4;
		void show() {
			int num = 5;
			System.out.println(num); //5
			System.out.println(this.num); // 4
			System.out.println(Outer.this.num); // 3
		}
	}
	void method() {
		new Inner().show();
	}
}


内部类也可以放在局部位置上
public class InnerClassDemo {
	public static void main(String[] args) {
		new Outer().method();
	}
}
class Outer{
	int num = 3;
	void method() {
		class Inner{
			int num = 4;
			void show() {
				System.out.println(num); //4
			}
		}
		new Inner().show();
	}
}

从内部类中访问局部变量x,需要被声明为final类型:
class Outer{
	int num = 3;
	void method() {
		final int x = 9;//从内部类中访问局部变量x,需要被声明为final类型
		class Inner{
			int num = 4;
			void show() {
				System.out.println(x);
			}
		}
		new Inner().show();
	}
}
因为Inner虽然是在局部位置上,但它是一个类,是可以创建对象的,method方法执行完之后,非final修饰的局部变量x就消失了,但是创建出来的Inner对象可能还在被某个变量所指向,这时候就会导致inner对象需要访问局部变量x时访问不到,所以就需要用final修饰x



匿名内部类:
使用的前提:内部类必须继承或实现一个外部类或者接口
public class InnerClassDemo {
	public static void main(String[] args) {
		new Outer().method();
	}
}
abstract class Demo{
	abstract void function();
}
class Outer{
	/*class Inner extends Demo{
		void function() {
			System.out.println("function");
		}
	}*/
	void method() {
//		new Inner().function();
		new Demo(){
			void function() {
				System.out.println("function");
			}
		}.function();
	}
}



匿名内部类的使用场景:
当函数的参数是接口类型,并且接口中的方法不超过三个时,可以用匿名内部类作为实际参数传递


匿名内部类使用注意事项:
public class InnerClassDemo1 {
	public static void main(String[] args) {
		new Outer().method();
	}
}
class Outer{
	void method(){
		new Object(){
			void show(){
				System.out.println("show");
			}
		}.show();
		// 以下方式编译失败,因为匿名内部类这个子类对象被向上转型为了Object类型,
		// 这样就不能再使用子类的特有方法了,参考多态
		/*Object obj = new Object(){
			void show(){
				System.out.println("show");
			}
		};
		obj.show();*/
	}
}


对象的初始化过程:
一个对象的实例化过程:
Person p = new Person();
1、JVM会读取指定路径下的Person.class文件,并加载进内存,同时会加载Person的父类(假设Person有父类)
2、在堆内存中开辟空间,分配地址
3、在堆内存的对象空间中对对象的属性进行默认初始化
4、调用对应的构造函数进行初始化
5、在构造函数中,第一行会先调用父类的构造函数进行初始化
6、父类初始化完毕后,再对本类的属性进行显示初始化
7、显示初始化完成之后,是构造代码块初始化
8、再进行本类构造函数的特定初始化
9、所有初始化完毕后,将地址赋给引用变量 p




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值