static,final,单例设计模式和abstract(保姆级笔记)

26 篇文章 3 订阅

 

目录

Static修饰符

Static变量

静态方法和非静态方法

静态代码块

匿名代码块

         单例设计模式

单例的饿汉式实现 

 单例的懒汉式实现:

视频笔记——饿汉式与懒汉式的对比: 

final修饰符

修饰成员变量-非静态成员变量 :

 修饰成员变量-静态成员变量:

final修饰引用变量

面试题

抽象类

模板方法设计模式的相关笔记


Static修饰符

Static变量

视频笔记:我们编写一个类时只是在描述对象的属性和行为,只有通过new关键字才会产生对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用。但是有时候希望无论处理了多少对象,都希望某些特定的数据在内存空间中只有一份,例如很多学生都是一个学校的,不必在每一个学生的实例对象中都单独分配一个用于代表学校名称的变量。

 下面看一段代码

public class student {
	int age;
	static String name;
	public static void main(String[] args)
	{
  student a1=new student();
  student a2=new student();
  a1.age=10;
  a1.name="小明";
  a2.age=20;
  System.out.println(a1.age);
  System.out.println(a2.age);
  System.out.println(a1.name);
  System.out.println(a2.name);
		
}
}

 虽然没有给a2的属性name赋值,但是输出的结果和a1一样,这就体现了static静态变量对于类而言在内存中只有一个,能被类的所有实例所共享

public class student {
	int age;
	static String name;
	public static void main(String[] args)
	{
  student a1=new student();
  student a2=new student();
  a1.age=10;
  a1.name="小明";
  a2.age=20;
  a2.name="小王";
  System.out.println(a1.age);
  System.out.println(a2.age);
  System.out.println(a1.name);
  System.out.println(a2.name);
		
}
}

 

 当为a2.name赋值时,a1.name也随之改变

实例变量:修改对象中的一个非静态属性时,不会使其他对象中同样的属性发生改变

静态变量:多个对象共享同一个静态变量

  • 静态变量随着类的加载而加载“可以通过类.静态变量”的方式进行调用
  • 静态变量的加载早于对象的创建
  • 由于类只会加载一次,则静态变量在内存中也只保存一份,存在于方法区的静态域中

静态方法和非静态方法

静态方法 " 不可以 " 直接访问类中的非静态变量和非静态方法 , 但是 " 可以 " 直接访问类中的静态变量和静态
方法
注意 :this super 在类中属于非静态的变量 .( 静态方法中不能使用 )
public class student {
	int age;
	static String name;
	public void a() {}
	public static void b() {}
	public static void test()
	{
		System.out.println(age);//编译报错
	}
}

 

 若改为name则编译通过

当把static去掉,为非静态方法时

非静态方法"可以"直接访问类中的非静态变量和非静态方法,也"可以"直接访问类中的静态变量和静态方法
父类的静态方法可以被子类继承,但是不能被子类重写
public class student {
	int age;
	public static void b() {}
}
public class studentA extends student//继承父类
{
public void b()//编译报错
{
	System.out.println(this.age);
}
}

 继承但不重写的时候

public static void main(String[] args)
{
studentA A=new studentA();
A.b();
} 	

编译通过,但不是重写 

父类非静态方法也不能被子类重写为静态方法


public class student {
	int age;
	public  void b() {}
}
public class studentA extends student//继承父类
{
	public static void b();//编译报错
}

静态代码块

static{

}
          静态代码块是在类加载完成之后就自动执行 ,并且只执行一次.
作用 :静态代码块的作用是给类中的静态成员变量初始化赋值
public class student {
	public static int age;
	static
	{ 
		age=1;
	}
	public  void b() {
		age=2;
	}
	public static void main(String[] args)
	{
     System.out.println(student.age);
    }
}

视频笔记:

在构造器中给静态变量赋值 , 并不能保证能赋值成功 , 因为构造器是在创建对象的时候才指向 , 但是 静态变量可以不创建对象而直接使用类名来访问
子类中非静态属性的显示赋值是在父类构造器执行完之后和子类中的匿名代码块执行之前的时候

匿名代码块

public class s{
{
 //匿名代码

}
}
视频笔记:因为没有名字 , 在程序并不能主动调用这些代码块。
匿名代码块是在创建对象的时候自动执行的 , 并且在构造器执行之前。同时匿名代码块在每次创建对象的时候都会自动执行 
public class student {
private int age;
	public student()
	{
		System.out.println("student构造器");
		test();
	}
	public void test()
	{
		System.out.println("student  test方法:age="+age);
	}
}
public class studentA extends student//继承父类
{
private int age=10;
	{
		System.out.println("子类匿名代码块");
	}
	static {
		System.out.println("子类静态代码块");
	}
	public studentA()
	{
		System.out.println("子类构造器");
	}
	public void test()
	{
		System.out.println("子类studentA test方法:age="+age);
	}
public static void main(String[] args)
{
	new studentA();
} 	
}

子类中非静态属性的显示赋值是在父类构造器执行完之后和子类中的匿名代码块执行之前 

口诀:由父及子,静态先行 

视频笔记: 

  1.  代码块的作用:用来初始化类,对象。
  2. 代码块如果有修饰的话,只能使用static。
  3. 分类:静态代码块和非静态代码块
  4. 静态代码块
  • 内部可以有输出语句
  • 随着类的加载而执行,而且只执行一次
  • 作用:初始化类的信息
  • 如果一个类中定义了多个静态代码块,则按照声明的先后顺序执行
  • 静态代码块的执行要优先于非静态代码块的执行
  • 静态代码块不能调用非静态的结构

非静态代码块

  •  内部可以有输出语句
  • 随着对象的创建而执行
  • 每创建一个对象,就执行一次非静态代码块
  • 作用:可以在创建对象时,对对象的属性等进行初始化
  • 如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
  • 非静态代码块内可以调用非静态的属性,静态的方法,或非静态的属性,非静态的方法

         单例设计模式

定义:采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例。 

单例的饿汉式实现 

  1. 私有化构造器
  2. 内部创建类的对象
  3. 提供公共的方法,返回类的对象
  4. 要求此对象也必须声明为静态的
public class demo{
	public static void main(String[] agrs)
	{
		bink b=bink.test();
		bink c=bink.test();
		System.out.println(b==c);
	}
}
 class bink{
//私有化构造器
	private bink() {
	}
//内部创建类的对象,要求此对象必须也是静态的
	private static bink a=new bink();
//提供公共的静态方法,返回类的对象
	public static bink test()
	{
		return a;
	}
}

 单例的懒汉式实现:

  1. 私有化类的构造器
  2. 声明当前类的对象,没有初始化
  3. 声明public,static 的返回当前对象的方法
public class demo{
	public static void main(String[] agrs)
	{
		bink b=bink.test();
		bink c=bink.test();
		System.out.println(b==c);
	}
}
 class bink{
//私有化构造器
	private bink() {
	}
//声明当前类对象,没有初始化,此对象必须也声明为静态的
	private static bink a=null;
//声明public,static的返回当前类对象的方法
	public static bink test()
	{
		if(a==null)
		{
		a=new bink();
		}
		return a;
	}
}

视频笔记——饿汉式与懒汉式的对比: 

饿汉式:缺点:加载时间过长。优点:饿汉式是线程安全的。

懒汉式:优点:延迟对象的创建。缺点:线程不安全。

视频笔记——属性赋值的先后顺序

默认初始化——显示初始化/在代码块中赋值——构造器中初始化——通过属性.对象属性.方法进行赋值

final修饰符

1.final修饰的类不能被继承,没有子类.比如String类,System类,StringBuffer类

 

 编译报错

2.用 final 修饰的方法可以被继承 , 但是不能被子类重写。比如Object中的getClass()方法

编译报错

 3.用final变量表示常量,只能被赋一次值.其实使用fifinal修饰的变量也就成了常量了,因为值不会再变。

当对a进行2次赋值时编译报错

public class Person{
 private final int a;
}

视频笔记: 

修饰成员变量-非静态成员变量 :

  • 只有一次机会 , 可以给此变量 a 赋值的位置 :
    声明的同时赋值
    匿名代码块中赋值
    构造器中赋值 ( 类中出现的所有构造器都要写 )
public class Person{ 
private static final int a; 
}

 修饰成员变量-静态成员变量:

  • 只有一次机会 , 可以给此变量 a 赋值的位置 :
    声明的同时赋值
    静态代码块中赋值

final 修饰局部变量:

尤其是使用final修饰形参时,表面此形参是一个常量,当我们调用此方法时,给常量形参赋一个实参,一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值

final修饰引用变量

public  class student {
String name;
public student()
{
	
}
public void set(String name)
{
	this.name=name;
}
public static void main(String[] args)
{
	final student a1=new student();
a1.set("xx");
a1.set("yy");
}
}

编译通过

new一次以后

编译报错

面试题

1.改错

public class s{
public int add(final x)
{
return ++x;
}
}

编译报错,应改为

public class s{
public int add(final x)
{
return x+1;
}
}

2.

public class some{
public static void main(String[] args)
{
other o=new other();
new some().add(o);
}
public void add(final other o)
{//o=new other();
o.i++
}
class other{
public int i;
}

编译通过,o是常量,但是i是变量,所以是没问题的

抽象类

使用abstract关键字定义的类称为抽象类,而使用这个关键字定义的方法称为抽象方法。抽象方法没有方法体,这个方法本身没有任何意义,除非它被重写,而承载这个抽象方法的抽象类必须被继承,实际上抽象类除了被继承没有任何意义。定义抽象类的语法如下:

public abstract class parent{
abstract void test();//定义抽象方法
}
视频笔记:1.声明类的同时 , 加上 abstract 修饰符就是抽象类 。2.声明方法的时候, 加上 abstract 修饰符 , 并且去掉方法的大口号 , 同时结尾加上分号 , 该方法就是抽象方法。
public  class student {
String name;
public student()
{	
}
public static void main(String[] agrs)
{
st s1=new st(1);//编译失败
}
}
abstract class st{
	int age;
	public st(int age)
	{
		this.age=age;
	}
}

 编译报错

当把abstract去掉后则正常

1.抽象类 , 不能使用 new 关键字来创建对象 , 它是用来让子类继承的。
2.抽象方法 , 只有方法的声明 , 没有方法的实现 , 它是用来让子类实现的
3.子类继承抽象类后 , 需要实现抽象类中没有实现的抽象方法 , 否则这个子类也要声明为抽象类
public  abstract class student {
String name;
public abstract void test();
 class st extends student{
	public void test()
	{
		
	}
 }
 

编译通过

笔记:1.重写抽象方法时即可实现同名方法但又非同目的的要求,提高了程序的可扩展性。
           2. 抽象类一定有构造器,便于子类实例化时调用。
           3.抽象方法只有方法的声明,无方法体
           4.包含抽象方法的类一定是抽象类
           5. 开发中都会提供抽象类的子类,让子类对象实例化,完成相关操作
           6.abstract不能用来修饰属性,构造器等结构,不能修饰私有方法,静态方法

抽象类是用来模型化那些父类无法确定全部实现,而是由子类提供具体实现对象的类。

代码举例

public abstract class employee {
private String name;
private int id;
private double salary;
public employee()
{
	super();
}
public employee(String name,int id,double salary)
{
	this.name=name;
	this.id=id;
	this.salary=salary;
}
	public abstract void work();//抽象方法
}
public class manger extends employee {
	private double bonus;
	public manger(double bonus)
	{
		super();
		this.bonus=bonus;
	}
	public manger(String name,int id,double salary,double bonus)
	{
		super(name,id,salary);
		this.bonus=bonus;
	}
	public void work()
	{
		System.out.println("管理员工");
	}

}
public class commonemployee extends employee {
	public void work()
	{
		System.out.println("员工在一线车间生产产品");
	}

}
public class employeetest {
public static void main(String[] args)
{
	manger a1=new manger("小王",1000,4000,10000);
	a1.work();
	commonemployee b1=new commonemployee();
   b1.work();
}
}

 

模板方法设计模式的相关笔记

 情景:当功能内部一部分实现是确定的,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。

也就是在软件开发中实现一个算法,整体步骤很固定,通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现,这就是一种模板模式。

public class timetest {
	public static void main(String[] args)
	{
		st M=new st();
		M.spendtime();
	}
}
abstract class template{
	public void spendtime()
	{//计算某段代码执行所需要花费的时间
		long start =System.currentTimeMillis();
		code();//不确定的部分,易变的部分,
		long end =System.currentTimeMillis();
		System.out.println("花费的时间为:"+(end-start));
		
	}
	public abstract void code();
}
class st extends template{
	public void code()
	{
		for(int i=2;i<=1000;i++)
		{
			boolean a=true;
			for(int j=2;j<=Math.sqrt(i);j++)
			{
				if(i%j==0)
					a=false;
				break;
			}
			if(a)
			{
				System.out.println(i);
			}
		}
		
	}
}

常见的有数据访问的封装,junit单元测试等等

学习如逆水行舟,不进则退,和小吴一起加油吧

评论 52
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小吴有想法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值