Java后端_11

Vector v = new Vector();
Object obj = v.elementAt(i); //v.elementAt()返回的是一个Object对象
//Double D = (Double)obj;
//double d = D;
//以上把obj向下转型成Double再拆箱成double可以直接转成一个式子:
double d = (double)obj;

数组也继承了Object类,可以使用equas()和toString()等方法。所以可以认为数组是一种特殊的类

关键字native:到此接下来执行的就是底层的C/C++的代码了
可以用来修饰方法的关键字:static、final、abstract、native
多态存在很大部分是因为参数传递,形参是父类,实参是子类,形成多态,方便代码结构的扩展和整洁。

可以直接获取现在的月份,操作类似于Scanner:
导包:import java.util.Calendar;

Calendar c = Calendar.getInstance();//Calendar是单例模式,不能new出一个对象
//因为单例模式的构造器是private的,因此只能通过类调用静态方法getInstance()来获取对象
int month = c.get(Calendar.MONTH);//1月是0,二月是1......

static:静态的

引入:

某些特定属性可以在内存中只有一份,属于所有对象共有,不用再特定给每个对象进行定义,比如中国人的国家名称,这时候就需要static。
static可以修饰属性、方法、代码块、内部类

一、static修饰属性:属性分为静态属性(类变量)和非静态属性(实例变量)

1.非静态变量:当创建了类的多个对象,每个对象都拥有一套非静态属性,当修改一个对象中的非静态属性时,不会导致其他对象中的属性改变。
2.静态变量:创建了多个对象,多个对象共享同一个静态变量,当修改一个对象的静态变量时,其他对象调用此静态变量时,都是修改过的。
3.静态变量随着类的加载而加载,所以静态变量的加载早于对象的创建,并且类只会加载一次,所以静态变量在内存中也只会存在一份:存在方法区的静态域中。可以通过“类.静态变量”的方式进行调用
4.静态属性举例:System.out;Math.PI
5.内存解析:
在这里插入图片描述

二、static修饰方法:静态方法

1.静态方法随着类的加载而加载,可以通过"类.静态方法"的方式进行调用
2.静态方法中:只能调用静态属性和静态方法
非静态方法中:既可以调用非静态的方法和属性,也可以调用静态的方法和属性
3.在静态方法内,不能使用this和super关键字

三、开发中如何确定一个属性是否要声明为static:

1.属性是可以被多个对象所共享的,不会随着对象的不同而不同
2.类中的常量一般声明为static

四、开发中如何确定一个方法是否要声明为static:

1.操作静态属性的set、get方法或包含静态属性的方法通常设为static的
2.工具类中的方法,习惯上声明为static的(因为没必要去创建对象),比如:Math,Arrays,Collections

static使用举例:

class Person{
	private int id;
	//要求创建person对象时,id从201801开始,每创建一个对象,id变为201802,201803......
	//这时就需要定义一个static的init,每调用一次构造器就+1
	private static int init = 201801;
	public Person() {
		id  = init++;
	}
}

单例设计模式

设计模式

设计模式是在大量的实践中总结的代码结构、编程风格、以及解决问题的思考方式。类似于套路,或者说不同棋局的棋谱,可以免去我们思考,直接按照套路去编程。有23种经典的设计模式。
单例设计模式(Singleton):采取一定的方法保证这个对象在虚拟机中只能产生一个对象。
必须使类的构造器权限是private,这样就不能在类的外部new出对象了,只能在类的内部产生对象。为了在类的外部得到类内部的对象,需要调用类的某个静态方法以返回类内部创建的对象,由于静态方法只能访问类中的静态变量,所以类中的属性必须都是静态属性。

一、具体实现的两个方法:

1.饿汉式:

//饿汉式
class Person{
	//1.私有化构造器
	private Person() {
		
	}
	//2.类内部创建对象(static)
	private static Person p = new Person();
	//3.提供public、static的方法返回类的内部对象
	public static Person getInstance() {
		return p;
	}
}

2.懒汉式:

// 懒汉式
class Person {
	// 1.私有化构造器
	private Person() {

	}
	// 2.声明对象(static),但不初始化
	private static Person p = null;
	// 3.提供public、static的方法返回当前对象
	public static Person getInstance() {
		if (p == null) {// 判断当年p为空时即还没有创建对象时,在创建对象
			p = new Person();
		}
		return p;
	}
}

或者不提供返回类的方法,直接public static final Person p = new Person();加final是为了防止把p修改成null,这样就会把p释放了。

Person p1 = Person.p;
Person p2 = Person.p;//p2和p1是一个对象
Person.p = null;//p被释放了
Person p3 = Person.p;//此时p3和p1、p2就不是一个对象了

二、区分饿汉式和懒汉式

饿汉式:坏处:对象加载时间过长。好处:线程是安全的
懒汉式:好处:延迟对象的创建,节省内存。坏处:目前的写法线程不安全(具体修改见多线程那一章)

三、单例模式优点:

单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。如java.lang.Runtime

四、单例模式的应用场景:

网站计数器,应用程序的日志,数据库连接池,读取配置文件的类,windows的任务管理器和回收站等。

main方法

1.程序的入口
2.是一个静态方法
3.main方法要求权限是public,这样在虚拟机中才方便找到
4.main方法不需要返回类型,所以是void
5.main方法有参数列表(String[] args)是一个String型的数组,所以main方法可以作为我们与控制台交互的方式(之前交互的方式是Scanner)(具体方法:先编译一下,在解释字节码的时候进行交互,交互完运行程序即可)

代码块

代码块或称为初始化块(block)
形式:在类中直接用大括号{ },代码块只能用static修饰,其他的关键字都不能修饰代码块

一、代码块的作用:用来初始化类、对象

二、代码块分为:静态代码块、非静态代码块

静态代码块:

1.内部可以有输出语句

static{
	System.out.println("static block");
}

2.随着类的加载而执行;静态方法是随着类的加载而加载,不执行,当“类.静态方法”时才执行
3.静态代码块只执行一次
4.作用:对类中的静态属性就行初始化
5.如果一个类中定义了多个静态代码块,则按照声明的先后顺序进行执行
6.静态代码块的执行优先于非静态代码块的执行
7.静态代码块只能调用静态结构

非静态代码块:

1.内部可以有输出语句

{
	System.out.println("block");
}

2.随着对象的加载而执行;非静态方法是随着对象的加载而加载,不执行
3.每创建一个对象,就执行一次非静态代码块
4.作用:可以在创建对象时,对对象的属性就行初始化
5.如果一个类中定义了多个非静态代码块,则按照声明的先后顺序进行执行
6.非静态代码块既可以调用静态结构,也可以调用非静态结构

代码块的执行先于构造器,原因:new一个对象本质是调用类的构造器,但是在调用构造器时得先加载类,加载类的时候静态代码块就已经执行了,而非静态代码块在加载对象时也执行了,所以构造器执行之前得先执行代码块。

对属性赋值的位置:

1.默认初始化
2.显式初始化
3.构造器初始化
4.有了对象后,通过“对象.属性”赋值
5.代码块中赋值
执行的顺序:1-> 2/5-> 3-> 4(2和5看声明的顺序,如果先写int age = 10;再写代码块{age = 11;}则先执行2再执行5;如果先写代码块{age = 11;},再写int age = 10;则先5后2)

final:最终的

一、final可以修饰类、方法、变量

二、final修饰类:最终的类,此类不能被其他类继承。比如:String类,System类,StringBuffer类

在这里插入图片描述
在这里插入图片描述

三、final修饰方法:最终的方法,此方法不可以被重写。比如:Object类中的getClass()方法

在这里插入图片描述
在这里插入图片描述

四、修饰变量:最终的变量,此变量成为一个常量。类似于C/C++的const

1.final修饰属性:可以赋值的位置:显式初始化、代码块中初始化、构造器中初始化。不能通过set方法或者“对象.属性”进行赋值

class A{
	final int A1 = 0;//显式初始化
	final int A2;
	final int A3;
	{
		A2 = 1;//代码块中初始化
	}
	A(int num){
		A3 = num;//构造器中初始化
	}
}

2.final修饰局部变量:是一个常量,不能修改。当final修饰的是形参时,表明此形参是常量,当调用此方法时,给常量赋一个实参,一旦赋值后,只能在方法体内使用形参,不能修改形参。

class Person{public int i;}
public void add(final Person p) {
	p.i++;//这个没问题,因为final修饰的是p不是i,p的地址没变就可以,i变不变都行。若是在方法中有p=new Person();则出错
}

五、static final修饰属性:全局常量。static final也可以修饰方法,不过见的少。

abstract:抽象的

一、abstract可以用来修饰类和方法

二、abstract修饰类:抽象类

1.此类不能实例化
2.抽象类中一定有构造器,便于子类实例化时调用(子类的构造器需要调用super();)
3.开发中,都会提供抽象类的子类,让子类对象实例化

三、abstract修饰方法:抽象方法(类似于C++中的虚函数)

1.抽象方法只有方法的声明,没有方法体。
如public abstract void eat();//不用写{},因为没有方法体
2.包含抽象方法的类一定是一个抽象类。(因为抽象方法没有方法体,调用抽象方法是无意义的,所以不能调用抽象方法,所以类必须是抽象类,因为抽象类无法实例化对象,也就无法调用抽象方法了)反之,抽象类中可以没有抽象方法。
3.若子类重写了父类中的所有的抽象方法后,此子类才可以实例化。若子类没有重写父类所有的抽象方法,则此类必须是抽象类,需用abstract进行修饰。

四、注意点

1.abstract不能用来修饰属性、构造器等结构。
2.abstract不能用来修饰私有方法(因为不能被重写),不能修饰静态方法(子父类中的同名同参的静态方法不构成重写,非静态的才算重写),不能修饰final的方法(因为final的方法不能被重写),不能修饰final的类(可以看出final和abstract是不相容的)

抽象类和抽象方法举例:

public abstract class Employee {
	private String name;
	private int id;
	private double salary;
	public Employee() {
		
	}
	public Employee(String name,int id,double salary) {
		this.name=name;
		this.id=id;
		this.salary=salary;
	}
	public abstract void work();
}
public class Manager extends Employee{
	private double bonus;//奖金
	public Manager() {
		
	}
	public Manager(String name, int id, double salary, double bonus) {
		super(name, id, salary);
		this.bonus = bonus;
	}

	@Override
	public void work() {
		System.out.println("管理员工");
	}
}
public class CommonEmployee extends Employee{
	@Override
	public void work() {
		System.out.println("咱是一线打工人");
	}
}

匿名子类的概念

public class EmployeeTest {
	public void method(Employee e) {//发生多态
		e.work();
	}
	
	
	public static void main(String[] args) {
		EmployeeTest et = new EmployeeTest();
		Manager m = new Manager();
		et.method(m);//非匿名类、非匿名对象
		
		et.method(new Manager());//匿名子类对象
		
		//如果我们需要再声明一个Cleaner子类(继承Employee),并且Cleaner子类只需要new一个对象并当成实参传递
		//那么我们就没有必要去再创建一个Cleaner类,然后再new一个对象进行传递。这样太麻烦了
		//可以直接使用匿名子类:
		Employee eCleaner = new Employee() {
			@Override
			public void work() {
				System.out.println("打扫卫生");
			}
		};
		//首先,eCleaner肯定不是Employee类,因为Employee类是抽象类,不能实例化,然后eCleaner重写了抽象方法
		//所以eCleaner肯定是Employee的子类。所以这是一个没有名字的子类,成为匿名子类。匿名子类方便进行一次性的参数传递:
		et.method(eCleaner);
	}
}

输出:
在这里插入图片描述

模板方法设计模式

抽象类体现的是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为
解决的问题:
当功能内部一部分实现是确定的,一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。
换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变的部分可以抽象出来,供不同子类实现。这就是一种模板模式。

举例:

public abstract class Template {
	public void spendTime(){//计算某段代码执行的时间
		long start = System.currentTimeMillis();
		testCode();
		long end = System.currentTimeMillis();
		System.out.println("代码执行的时间为"+(end-start));
	}
	
	//要测试的代码是可变的,写成抽象方法
	public abstract void testCode();
}

class subTemplate extends Template{
	//计算输出1000以内的质数的时间
	@Override
	public void testCode() {
		for(int i=2;i<=1000;i++) {
			boolean isFlag = true;
			for(int j=2;j<=Math.sqrt(i);j++) {
				if(i%j==0) {
					isFlag = false;
					break;
				}
			}
			if(isFlag) {
				System.out.println(i);
			}
		}
		
	}
}

public class TemplateTest {
	public static void main(String[] args) {
		Template t = new subTemplate();
		t.spendTime();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值