高级类特性(二)

一、toString方法

1)在Object这个类中,关于toString方法,是这样定义的。

public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

所以当我们在打印一个对象的引用时,实际上默认调用的就是这个对象的toString()方法

2)当我们打印的对象所在的类没有重写Object中的toString()方法时,那么调用的就是Object类中定义的toSrting方法,返回值为此对象所在的类及其堆空间对象实体的首地址值。

3)当我们打印的对象的类重写了Object中的toString()方法时,则调用我们重写的toString方法

常常在类的定义中重写toString方法来返回这个类创建的对象的属性值。

二、Junit测试//可能笔记不对 待修正

通常将main方法作为测试方法,会导致代码过多,用JAVA提供的类库Junit可以进行测试。

1.右键工程-构建路径-配置构建路径-库-Add Library-Junit-Junit5

2.在测试方法上面一行 要有 @org.junit.Test

3.源码处右键-运行Junit测试方法

可代替main方法作为测试方法,并且在测试方法所属类中的其他方法可直接调用,并不用重新创建一个对象。

三、包装类(Wrapper)

package com.xijian.java;
import org.junit.Test;
//包装类:8种基本的数据类型都对应着一个类,此类即为包装类
//基本数据类型 包装类 及String之间的相互转换
//注意:如在一个类中定义了一个包装类的对象,那么这个对象初值为null,而不是false
public class Demo {
	//基本数据类型与包装类之间的转换
	@Test
	public void test1() {
	int i = 10;
	System.out.println(i);
	boolean b = false;
	//基本数据类型--->对应的包装类,调用包装类的构造器
	Integer i1 = new Integer(i);
	System.out.println(i1.toString());//在包装类种toString方法已被重写
	
	Float f = new Float(12.3F);
	System.out.println(f);
	//报错java.lang.NumberFormatException
	//i1 = new Integer("12abc");   Integer构造器可以接收一个字符型的值,但字符型种必须也是一个数字字符串
	//System.out.println(i1);
	Boolean b1 = new Boolean("true");
	System.out.println(b1);//true
	b1 = new Boolean("true123");
	System.out.println(b1);//false 布尔类型特殊,除true之外其他任何值都不报错,而是相当于false
	
	//包装类--->基本数据类型:调用包装类的xxxValue方法转换回去
	int i2 = i1.intValue();//拆箱
	System.out.println(i2);
	
	//JDK5.0后 有自动装箱和拆箱的功能 上面的东西可以都忘了- - 
	Integer i3 = 12;//自动装箱
	int i4 = i3;//自动拆箱
	System.out.println(i3+i4);

	
}
	//基本数据类型、包装类--->String类:调用String类的valueof()方法
	@Test
	public void test2() {
		int i5 = 10;
		String i6 = 10+"";//"10"
		
		String str2 = String.valueOf(i6);
		String str3 = String.valueOf(true);
		//String类型转换为基本类型、包装类型:调用包装类的parseXXX()方法
		int i7 = Integer.parseInt(str2);
		System.out.println(i7);
		
		boolean b3 = Boolean.parseBoolean(str3);
		System.out.println(b3);
	}
}

四、static关键字

package com.atguigu.java1;
/*
 * static,静态的,可以用来属性、方法、*代码块(或初始化块)、*内部类
 * 
 * static修饰属性(类变量):
 * 1.由类创建的所有的对象,都共用这一个属性
 * 2.当其中一个对象对此属性进行修改,会导致其他对象对此属性的一个调用。vs 实例变量(非static修饰的属性,各个对象各自拥有一套副本)
 * 3.类变量随着类的加载而加载的,而且独一份
 * 4.静态的变量可以直接通过“类.类变量”的形式来调用
 * 5.类变量的加载是要早于对象。所以当有对象以后,可以“对象.类变量”使用。但是"类.实例变量"是不行的。
 * 6.类变量存在于静态域中。
 * 
 * static修饰方法(类方法):
 * 1.随着类的加载而加载,在内存中也是独一份
 * 2.可以直接通过“类.类方法”的方式调用
 * 3.内部可以调用静态的属性或静态的方法,而不能调用非静态的属性或方法。反之,非静态的方法是可以调用静态的属性或静态的方法
 * 	>静态的方法内是不可以有this或super关键字的!
 * 注:静态的结构(static的属性、方法、代码块、内部类)的生命周期要早于非静态的结构,同时被回收也要晚于非静态的结构
 */
public class TestSportsMan {
	public static void main(String[] args) {
		SportsMan s1 = new SportsMan("金龙",23);
		SportsMan s2 = new SportsMan("银龙",21);
		s1.name = "花龙";
		s1.nation = "China";
		System.out.println(s1);
		System.out.println(s2);
		System.out.println(SportsMan.nation);
//		SportsMan.show1();
		s1.show1();
		SportsMan.show();
		s1.show();
	}
}
class SportsMan{
	//实例变量(随着对象的创建而被加载的)
	String name;
	int age;
	//类变量
    static String nation;
	public SportsMan(String name, int age) {
		super();
		this.name = name;
		this.age = age;
		this.nation = "中国";
	}
	@Override
	public String toString() {
		return "SportsMan [name=" + name + ", age=" + age + ", nation="
				+ nation + "]";
	}
	
	public void show1(){
		System.out.println("age:" + this.age);
		System.out.println("nation:" + nation);
		info();
		System.out.println("我是一个来自于中国的运动员");
	}
	public static void show(){
		System.out.println("nation:" + nation);
		info();
//		this.show1();
		//System.out.println("age:" + this.age);
		System.out.println("我是一个来自于中国的运动员");
	}
	public static void info(){
		System.out.println("我是静态的方法!");
	}
}

static的变量的内存结构图


ps:使用静态的变量可以实现“累加”的效果,因为静态的变量在内存中独一份、

五、单例设计模式(饿汉式、懒汉式)

package com.atguigu.java;
/*
 * 设计模式:设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。
 * 23种设计模式。
 * 
 * 单例的设计模式:
 * 1.解决的问题:使得一个类只能够创建一个对象。
 * 2.如何实现?见如下的4步
 */
//饿汉式
public class TestSingleton {
	public static void main(String[] args) {
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		System.out.println(s1 == s2);
	}
}
//只能创建Singleton的单个实例
class Singleton{
	
	//1.私有化构造器,使得在类的外部不能够调用此构造器
	private Singleton(){
		
	}
	//2.在类的内部创建一个类的实例
	private static Singleton instance = new Singleton();
	//3.私有化此对象,通过公共的方法来调用
	//4.此公共的方法,只能通过类来调用,因为设置为static的,同时类的实例也必须为static声明的
	public static Singleton getInstance(){
		return instance;
	}
	
}
package com.atguigu.java;
//懒汉式:可能存在线程安全问题的
public class TestSingleton1 {
	public static void main(String[] args) {
		Singleton1 s1 = Singleton1.getInstance();
		Singleton1 s2 = Singleton1.getInstance();
		System.out.println(s1 == s2);
		
	}
}
class Singleton1{
	//1.私有化类的构造器
	private Singleton1(){
		
	}
	//2.声明一个该类的静态引用类型并私有化
	private static Singleton1 instance = null;
	//3.使用一个公共的静态方法创建对象并返回。
	public static Singleton1 getInstance(){
		
		if(instance == null){
			
			instance = new Singleton1();
		}
		return instance;
	}
}

六、代码块

package com.atguigu.java;

/*
 * 类的第四个成员:初始化块(或代码块)
 * 1.代码块如果有修饰的话,那么只能使用static。
 * 2.分类:
 * 静态代码块:
 * 1.里面可以有输出语句
 * 2.随着类的加载而加载,而且只被加载一次
 * 3.多个静态代码块之间按照顺序结构执行
 * 4.静态代码块的执行要早于非静态代码块的执行。
 * 5.静态的代码块中只能执行静态的结构(类属性,类方法)
 * 
 * 非静态代码块:
 * 1.可以对类的属性(静态的 & 非静态的)进行初始化操作,同时也可以调用本类声明的方法(静态的 & 非静态的)
 * 2.里面可以有输出语句
 * 3.一个类中可以有多个非静态的代码块,多个代码块之间按照顺序结构执行
 * 4.每创建一个类的对象,非静态代码块就加载一次。
 * 5.非静态代码块的执行要早于构造器
 * 
 * 关于属性赋值的操作:①默认的初始化②显式的初始化或代码块初始化(此处两个结构按照顺序执行) ③构造器中;④通过方法对对象的相应属性进行修改
 */
public class TestOrder {
	public static void main(String[] args) {
		Order o1 = new Order();
		System.out.println(o1);

		System.out.println();

		Order o2 = new Order();
		System.out.println(o2);
	}
}

class Order {

	private String orderName;
	private int orderId = 1001;
	private static String orderDesc;
	public Order() {
		super();
		System.out.println("我是Order类的空参的构造器");
	}
	//非静态的初始化块
	{
		orderId = 1002;
		orderName = "AA";
		System.out.println("我是非静态代码块1");
		orderDesc = "ORDER";
		show1();
		show2();
	}
	{
		orderId = 1003;
		System.out.println("我是非静态代码块2");
	}
	//静态的代码块
	static{
		System.out.println("静态代码块2");
		orderDesc = "我是一个Order";
//		orderId = 1000;
//		show1();
		show2();
	}
	static{
		System.out.println("静态代码块1");
	}

	public Order(int orderId, String orderName) {
		super();
		this.orderId = orderId;
		this.orderName = orderName;
	}

	public int getOrderId() {
		return orderId;
	}

	public void setOrderId(int orderId) {
		this.orderId = orderId;
	}

	public String getOrderName() {
		return orderName;
	}

	public void setOrderName(String orderName) {
		this.orderName = orderName;
	}

	@Override
	public String toString() {
		return "Order [orderId=" + orderId + ", orderName=" + orderName + "]";
	}
	public void show1(){
		
	}
	public static void show2(){
		
	}

}

七、final关键字

package com.atguigu.java1;
/*
 * final:最终的 ,可以用来修饰类、属性、方法
 * 
 * 1.final修饰类:这个类就不能被继承。如:String类、StringBuffer类、System类
 * 
 * 2.final修饰方法:不能被重写。如:Object类的getClass()
 * 
 * 3.final修饰属性:此属性就是一个常量,一旦初始化后,不可再被赋值。习惯上,常量用大写字符表示。
 * 此常量在哪里赋值:①此常量不能使用默认初始化 ②可以显式的赋值、代码块、构造器。
 * 
 * 变量用static final修饰:全局常量
 * 
 * >与finally finalize()区分开
 * 
 */
public class TestFinal {
	public static void main(String[] args) {
		C c = new C();
		System.out.println(c.getClass());
		System.out.println(Math.PI);
	}
}

class D{
	final int I = 12;
	final double PI;
	final String NAME;

	public void m1(){
		System.out.println(I);
//		I = 10;

	}
	{
		PI = 3.14;
	}
	
	public D(){
		NAME = "DD";
	}
	public D(String name){
		this();
		//NAME = name;
	}
}

//class SubString extends String{
//	
//}
final class A{
	
}
//class B extends A{
//	
//}
class C{
	public final void method1(){
		System.out.println("method1");
	}
}

class E extends C{
//	public void method1(){
//		System.out.println("method1...");
//	}
}

对下列两个代码进行排错


首先因为形参x是final类型的所以一旦赋值就不允许再改变,不能再进行自加运算。

第二个代码因为final类型声明的是一个类的引用,而这个类中的变量并不是final的,所以这个类不能被继承但里面的变量可以改变。

八、abstract 抽象类 抽象方法

package com.atguigu.java1;
/*
 * abstract:抽象的,可以用来修饰类、方法
 * 
 * 1.abstract修饰类:抽象类
 * 1)不可被实例化
 * 2)抽象类有构造器 (凡是类都有构造器)
 * 3)抽象方法所在的类,一定是抽象类。
 * 4)抽象类中可以没有抽象方法。
 * 
 * 2.abstract修饰方法:抽象方法
 * 1)格式:没有方法体,包括{}.如:public abstract void eat();
 * 2)抽象方法只保留方法的功能,而具体的执行,交给继承抽象类的子类,由子类重写此抽象方法。
 * 3)若子类继承抽象类,并重写了所有的抽象方法,则此类是一个"实体类",即可以实例化
 * 4)若子类继承抽象类,没有重写所有的抽象方法,意味着此类中仍有抽象方法,则此类必须声明为抽象的!
 * 
 */
public class TestAbstract {
	public static void main(String[] args) {
		//Person p1 = new Person();
		//p1.eat();
		
		Student s = new Student();
		s.eat();
		
		Person p = new Student();//多态
		p.eat();
		
	}
}

abstract class Creator{
	abstract void breath();
}

abstract class Person extends Creator{
	String name;
	public abstract void eat();
	public abstract void walk();
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Person(){
		
	}
	public Person(String name){
		this.name = name;
	}
}
class Student extends Person{
	public void eat(){
		System.out.println("学生吃饭");
	}
	public void walk(){
		System.out.println("学生走路");
	}
	@Override
	void breath() {
		System.out.println("学生不应该呼吸雾霾的空气");
	}
}

abstract class Worker extends Person{
	public void eat(){
		System.out.println("工人吃饭");
	}
//	public void walk(){
//		System.out.println("工人走路");
//	}
}

class Animal{
	//不是抽象方法!
	public void sleep(){
		
	}
}

九、模板方法的设计模式

抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展,改造,但子类总体上会保留抽象类的行为方式。

可以解决的问题:

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

2)编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其子类实现,这是模板设计模式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值