高级类特性(二),类特性
高级类特性(二),类特性
一、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)编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其子类实现,这是模板设计模式。相关文章
- 暂无相关文章
用户点评