Peopie类和测试类的实现
案例题目
- 编程实现People类的封装,特征有:姓名、年龄、国籍,要求提供打印所有特征的方法
- 编程实现PeopleTest类,main方法中使用有参方式构造两个对象并打印
People.java
/*
编程实现People类的封装
*/
public class People{
// 1.私有化成员变量,使用private关键字修饰
private String name;
private int age;
private String country;
// 3.在构造方法中调用set方法进行合理值的判断
public People(){}
public People(String name,int age,String country){
setName(name);
setAge(age);
setCountry(country);
}
//2.提供公有的get和set方法,并在方法体中进行合理值的判断
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
if(age > 0 && age < 150){
this.age = age;
}else{
System.out.println("年龄不合理喔!");
}
}
public String getCountry(){
return country;
}
public void setCountry(String country){
this.country = country;
}
public void show(){
System.out.println("我是" + getName() + ",今年" + getAge() + "岁了,来自" + getCountry());
}
}
PeopleTest.java
/*
编程实现People类的测试
*/
public class PeopleTest{
public static void main(String[] args){
// 1.使用有参方式构造两个People类型的对象并打印特征
People p1 = new People("zhangfei", 30, "China");
p1.show(); // zhangfei 30 China
People p2 = new People("guanyu", 35, "China");
p2.show(); // guanyu 35 China
}
}
static关键字的基本概念
基本概念
- 使用
static关键字修饰成员变量表示静态的含义
,此时成员变量由对象层级提升为类层级
,也就是整个类只有一份并被所有对象共享,该成员变量随着类加载准别就绪,与是否创建对象无关
- static关键字修饰的成员可以使用
引用.
的方式访问,但推荐类名.
的方式
People.java
/*
编程实现People类的封装
*/
public class People{
// 1.私有化成员变量,使用private关键字修饰
private String name;
private int age;
// private String country; // 隶属于对象层级,也就是每个对象都拥有独立的一份
public static String country; // 隶属于类层级,也就是所有对象都共享同一份,测试修改为了public
// 3.在构造方法中调用set方法进行合理值的判断
public People(){}
public People(String name,int age,String country){
setName(name);
setAge(age);
setCountry(country);
}
//2.提供公有的get和set方法,并在方法体中进行合理值的判断
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
if(age > 0 && age < 150){
this.age = age;
}else{
System.out.println("年龄不合理喔!");
}
}
public String getCountry(){
return country;
}
public void setCountry(String country){
this.country = country;
}
public void show(){
System.out.println("我是" + getName() + ",今年" + getAge() + "岁了,来自" + getCountry());
}
}
PeopleTest.java
/*
编程实现People类的测试
*/
public class PeopleTest{
public static void main(String[] args){
// 3.验证static关键字修饰的静态成员(类成员)是否与创建对象无关 类名.的方式 =>无关
System.out.println("获取到的国籍信息是:" + People.country); //null
// 1.使用有参方式构造两个People类型的对象并打印特征
People p1 = new People("zhangfei", 30, "China");
p1.show(); // zhangfei 30 China
People p2 = new People("guanyu", 35, "China");
p2.show(); // guanyu 35 China
System.out.println("-----------------------------------------");
// 2.验证static关键字修饰的静态成员(类成员)是否被所有对象共享
p1.country = "蜀国";
System.out.println("第一个对象的国籍是:" + p1.country); // 蜀国
System.out.println("第二个对象的国籍是:" + p2.country); // 蜀国
People p3 = new People();
System.out.println("第三个对象的国籍是:" + p2.country); // 蜀国
}
}
没有static跟有static关键的对比如下:
static关键字的使用方式
使用方式
-
在非静态成员方法中既能访问非静态的成员又能访问静态的成员
(成员: 成员变量 + 成员方法,静态成员被所有对象共享)
-
在静态成员方法中只能访问静态成员不能访问非静态成员
(成员: 成员变量 + 成员方法,因为此时可能还没有创建对象)
-
在以后的开发中只有隶属于类层级并被所有对象共享的内容才可以使用static关键字修饰(不能滥用static关键字)
StaticTest.java
/*
编程实现static关键字的使用
*/
public class StaticTest{
private int cnt = 1; // 隶属于对象层级,也就是每个对象都拥有独立的一份
private static int snt = 2; // 隶属于类层级,也就是所有对象都共享同一份
// 自定义非静态的成员方法 需要使用引用.的方式访问
public void show(){
System.out.println("cnt = " + this.cnt); // 1
System.out.println("snt = " + this.snt); // 2 静态成员被所有对象,this关键字可以省略
}
// 自定义静态的成员方法 推荐使用类名.的方式访问
public static void test(){
// StaticTest st = new StaticTest();
// System.out.println("cnt = " + cnt); // 1 静态成员方法中没有this关键字,因为是可以通过类名.方式调用的
System.out.println("snt = " + snt); // 2
}
public static void main(String[] args){
StaticTest st = new StaticTest();
st.show();
System.out.println("-----------------------------------------");
StaticTest.test();
}
}
改造后的People.java
/*
编程实现People类的封装
*/
public class People{
// 1.私有化成员变量,使用private关键字修饰
private String name;
private int age;
// private String country; // 隶属于对象层级,也就是每个对象都拥有独立的一份
// public static String country; // 隶属于类层级,也就是所有对象都共享同一份
private static String country;
// 3.在构造方法中调用set方法进行合理值的判断
public People(){}
public People(String name,int age/*,String country*/){
setName(name);
setAge(age);
//setCountry(country);
}
//2.提供公有的get和set方法,并在方法体中进行合理值的判断
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
if(age > 0 && age < 150){
this.age = age;
}else{
System.out.println("年龄不合理喔!");
}
}
public static String getCountry(){
return country;
}
public void setCountry(String country){
//this.country = country;
People.country = country;
}
public void show(){
System.out.println("我是" + getName() + ",今年" + getAge() + "岁了,来自" + getCountry());
}
}
改造后的PeopleTest.java
/*
编程实现People类的测试
*/
public class PeopleTest{
public static void main(String[] args){
// 3.验证static关键字修饰的静态成员(类成员)是否与创建对象无关 类名.的方式 =>无关
// System.out.println("获取到的国籍信息是:" + People.country); //null
System.out.println("获取到的国籍信息是:" + People.getCountry()); //null
// 1.使用有参方式构造两个People类型的对象并打印特征
People p1 = new People("zhangfei", 30/*, "China"*/);
p1.show(); // zhangfei 30 China
People p2 = new People("guanyu", 35/*, "China"*/);
p2.show(); // guanyu 35 China
System.out.println("-----------------------------------------");
// 2.验证static关键字修饰的静态成员(类成员)是否被所有对象共享
// p1.country = "蜀国";
p1.setCountry("蜀国");
// System.out.println("第一个对象的国籍是:" + p1.country); // 蜀国
// System.out.println("第二个对象的国籍是:" + p2.country); // 蜀国
System.out.println("第一个对象的国籍是:" + p1.getCountry()); // 蜀国
System.out.println("第二个对象的国籍是:" + p2.getCountry()); // 蜀国
People p3 = new People();
//System.out.println("第三个对象的国籍是:" + p2.country); // 蜀国
System.out.println("第三个对象的国籍是:" + p2.getCountry()); // 蜀国
}
}
构造块和静态代码块(熟悉)
构造块
:在类体中直接使用{}
括起来的代码块- 每创建一个对象都会执行一次构造块
静态代码块
:使用static关键字修饰的构造块- 静态代码块
随着类加载时执行一次
/*
编程实现构造块和静态代码块的使用
*/
public class BlockTest{
// 当需要在执行构造方法体之前做一些准备工作时,则将准备工作的相关代码写在构造块中即可,比如:对成员变量进行的统一初始化操作
{
System.out.println("构造块!"); // (2)
}
// 静态代码块会随着类加载而准备就绪,会先于构造块执行
// 当需要在执行代码块之前随着类的加载做一些准备工作时,则编写代码到静态代码块中国,比如:加载数据库的驱动包等
static{
System.out.println("################静态代码块!"); // (1)
}
// 自定义构造方法
public BlockTest(){
System.out.println("=====构造方法体!"); // (3)
}
public static void main(String[] args){
BlockTest bt = new BlockTest();
BlockTest bt2 = new BlockTest();
}
}
main方法的详解
-
语法格式:
public static void main(String[] args){}
-
参数使用的举例
/*
编程实现main方法的测试
*/
public class MainTest{
public static void main(String[] args){
System.out.println("参数数组中元素的个数是:" + args.length);
System.out.println("传递给main方法的实际参数为:");
for(int i = 0; i < args.length; i++){
System.out.println("下标为" + i + "形参变量数值为:" + args[i]);
}
}
}
Singleton和SingletonTest类的框架实现
案例题目(重中之重
)
- 编程实现Singleton类型的封装
- 编程实现SingletonTest类对Singleton类进行测试,要求
main方法中能得到且只能得到该类的一个对象
Singleton.java
/*
编程实现Singleton类的封装
*/
public class Singleton{
// 2.声明Singleton本类类型的引用指向本类类型的对象,使用private static关键字共同修饰
private static Singleton sin = new Singleton();
// 1.私有化构造方法,使用private关键字修饰
private Singleton(){
}
// 3.提供公有的get方法负责将对象返回出去, 使用private static关键字共同修饰
public static Singleton getInstance(){
return sin;
}
}
SingletonTest.java
/*
编程实现Singleton类的测试
*/
public class SingletonTest{
public static void main(String[] args){
// 1.声明Singleton类型的引用指向该类型的对象
// Singleton s1 = new Singleton();
// Singleton s2 = new Singleton();
// System.out.println(s1 == s2); // 比较变量s1的数值是否与变量s2的数值相等 false
// Singleton.sin = null; 可以使得引用变量无效
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2); // true
}
}
执行流程和内存结构分析
单例设计模式
但例设计模式的概念
- 在某些特殊场合中,
一个类对外提供且只提供一个对象时
,这样的类叫做单例类,而设计单例的流程和思想叫做单例设计模式
单例设计模式的实现流程
私有化构造方法,使用private关键字修饰
声明本类类型的引用指向本类类型的对象
,并使用private static关键字共同修饰
提供公有的get方法负责将对象返回出去
,并使用public static关键字共同修饰
单例设计模式的实现方式
- 单例设计模式的实现方式有两种:
饿汉式 和懒汉式
,在以后的开发中推荐饿汉式
/*
编程实现Singleton类的封装
*/
public class Singleton{
// 2.声明Singleton本类类型的引用指向本类类型的对象,使用private static关键字共同修饰
// private static Singleton sin = new Singleton(); // 饿汉式
private static Singleton sin = null; // 懒汉式
// 1.私有化构造方法,使用private管金子修饰
private Singleton(){
}
// 3.提供公有的get方法负责将对象返回出去, 使用private static关键字共同修饰
public static Singleton getInstance(){
// return sin;
if(null == sin){
sin = new Singleton();
}
return sin;
}
}
继承的由来和概念
继承的概念
-
当多个类之间有相同的
特征和行为
时,可以将相同的内容提取出来组成一个公共类,让多个类吸收公共类中已有特征和行为而在多个类型只需要编写自己独有特征和行为的机制,叫做继承 -
在Java语言中使用
extends(扩展)
关键字来表示继承关系 -
如:
public class Work extends Person{} - 表示Worker类继承自Person类
其中Person类叫做超类、父类、基类
其中Worker类叫做派生类、子类、孩子类
-
使用继承提高了代码的复用性,可维护性及扩展性,是多态的前提条件
继承的特点
子类不能继承父类的构造方法和私有方法,但私有成员变量可以被继承只是不能直接访问
- 无论使用何种方式构造子类的对象时都会
自动调用父类的无参构造方法,来初始化从父类中继承的成员变量
,相当于在构造方法的第一行增加代码super的效果
- 使用继承必须满足逻辑关系:
子类is a父类
,也就是不能滥用继承 - 在java语言中只支持单继承不支持多继承,也就说一个子类只能有一个父类,但一个父类可以有多个子类
继承的特点1
- 子类不能继承父类的构造方法和私有方法,但私有成员变量可以被继承只是不能直接访问
Person.java
/*
编程实现Person类的封装
*/
public class Person{
// 1.私有化成员比变量,使用private关键字修饰
private String name;
private int age;
// 3.在构造方法中调用get方法进行合理值的判断
public Person(){}
public Person(String name, int age){
setName(name);
setAge(age);
}
// 2.提供公有的get和set方法体中进行合理值的判断
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
if(age > 0 && age < 100){
this.age = age;
}else{
System.out.println("年龄不合理哦!");
}
}
// 自定义成员方法实现特征的打印
public void show(){
System.out.println("我是" + getName() + ",今年" + getAge() + "岁了!");
}
// 自定义成员方法描述吃饭的行为
public void eat(String food){
System.out.println(food + "真好吃!");
}
// 自定义成员方法描述娱乐的行为
public void play(String game){
System.out.println(game + "真好玩!");
}
}
Worker.java
/*
自定义Worker类继承自Person类
*/
public class Worker extends Person{
// 1.
private int salary;
public Worker(){}
public Worker(String name, int age, int salary){
setName(name);
setAge(age);
setSalary(salary);
}
public int getSalary(){
return salary;
}
public void setSalary(int salary){
if(salary >= 2200){
this.salary = salary;
}else{
System.out.println("薪水不合理哦!");
}
}
// 自定义成员方法描述工作的行为
public void work(){
System.out.println("今天的砖头有点烫手!");
}
}
WorkerTest.java
/*
编程实现Worker类的测试
*/
public class WorkerTest{
public static void main(String[] args){
// 1.使用无参方式构造Worker类型的对象并打印特征
Worker w1 = new Worker();
w1.show(); // null 0
System.out.println("---------------------");
// 2.使用有参方式构造Worker类型的对象并打印特征
Worker w2 = new Worker("zhangfei", 30, 3000);
w2.show(); // zhangfei ...
w2.eat("豆芽");
w2.play("王者荣耀");
w2.work();
}
}
继承的特点2
- 无论使用何种方式构造子类的对象时都会
自动调用父类的无参构造方法
,来初始化从父类中继承的成员变量
,相当于在构造方法的第一行增加代码super的效果
子类Worker.java
/*
自定义Worker类继承自Person类
*/
public class Worker extends Person{
private int salary;
public Worker(){
super(); // 表示调用父类的无参构造方法,若没有加则编译器自动添加
System.out.println("Worker()");
}
public Worker(String name, int age, int salary){
super(name,age); // 表示调用父类的有参构造方法
System.out.println("Worker(String,int,int)");
//setName(name);
//setAge(age);
setSalary(salary);
}
public int getSalary(){
return salary;
}
public void setSalary(int salary){
if(salary >= 2200){
this.salary = salary;
}else{
System.out.println("薪水不合理哦!");
}
}
// 自定义成员方法描述工作的行为
public void work(){
System.out.println("今天的砖头有点烫手!");
}
}
继承的特点3和4
- 使用继承必须满足逻辑关系:
子类is a父类
,也就是不能滥用继承 - 在java语言中只支持单继承不支持多继承,也就说一个子类只能有一个父类,但一个父类可以有多个子类
方法重写的概念和使用
方法重写的概念
从父类中继承下来的方法不满足子类的需求时,就需要在子类中重新写一个和父类一样的方法来覆盖从父类中继承的版本
,该方法就叫做方法的重写(Override)
方法重写的Worker.java
/*
自定义Worker类继承自Person类
*/
public class Worker extends Person{
// 1.
private int salary;
public Worker(){
super(); // 表示调用父类的无参构造方法,若没有加则编译器自动添加
System.out.println("Worker()");
}
public Worker(String name, int age, int salary){
super(name,age); // 表示调用父类的有参构造方法
System.out.println("Worker(String,int,int)");
//setName(name);
//setAge(age);
setSalary(salary);
}
public int getSalary(){
return salary;
}
public void setSalary(int salary){
if(salary >= 2200){
this.salary = salary;
}else{
System.out.println("薪水不合理哦!");
}
}
// 自定义成员方法描述工作的行为
public void work(){
System.out.println("今天的砖头有点烫手!");
}
// 自定义show方法覆盖从父类中继承的版本
@Override // 标注/注解,用于说明下面的方法是对父类方法的重写,若没有构成重写则编译报错
public void show(){
super.show();// 表示调用父类的show方法
System.out.println("我的薪水是:" + getSalary());
}
}
方法重写的原则
- 要求
方法名相同、参数列表相同以及返回值类型相同
,从Java5开始允许返回子类类型 - 要求
方法的访问权限不能变小,可以相同或者变大
- 要求方法不能抛出更大的异常(异常机制)
案例题目
- 编程实现Animal类的封装,特征有:名字和毛色,要求提供打印所有特征的方法
- 编程实现Dog类的封装并继承自Animal类,该类的特征有:牙齿数量,要求提供打印所有特征的方法
- 编程实现DogTest类,在main方法中分别使用无参和有参方式构造Dog类型对象并打印特征
Animal.java
package com.lagou.task08;
public class Animal {
private String name;
private String color;
public Animal() {
}
public Animal(String name, String color) {
setName(name);
setColor(color);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public void show(){
// sout 回车, 生成打印的语句
System.out.println("名字" + getName() + ",颜色" + getColor());
}
}
Dog.java
package com.lagou.task08;
public class Dog extends Animal {
private int tooth;
public Dog() {
super(); // 表示调用父类的无参构造方法 自动保存
}
public Dog(String name, String color, int tooth) {
super(name, color); // 表示调用父类的有参构造方法
setTooth(tooth);
}
public int getTooth() {
return tooth;
}
public void setTooth(int tooth) {
if (tooth > 0){
this.tooth = tooth;
}else {
System.out.println("牙齿数量不合理!");
}
}
@Override
public void show() {
super.show(); // 调用父类中的show()方法
System.out.println("牙齿数量是:" + getTooth());
}
}
DogTest.java
package com.lagou.task08;
public class DogTest {
public static void main(String[] args) {
// 1.使用无参方式构造Dog类型的对象并打印特征
Dog d1 = new Dog();
d1.show();
// 2.使用有参方式构造Dog类型的对象并打印特征
Dog d2 = new Dog("旺财", "白色", 10);
d2.show(); // 旺财 白色 10
}
}
构造块和静态代码块的考点
先执行父类的静态代码块,再执行子类的静态代码块
执行父类的构造块,执行父类的构造方法体
执行子类的构造块,执行子类的构造方法体
SuperTest.java
package com.lagou.task08;
public class SuperTest {
{
System.out.println("SuperTest类中的构造块!"); // (2) c
}
static {
System.out.println("SuperTest类中的静态代码块!"); // (1) a
}
public SuperTest(){
System.out.println("SuperTest类中的构造方法体!"); // (3) d
}
public static void main(String[] args){
// 使用无参方式构造对象
SuperTest st = new SuperTest();
}
}
SubSuperTest.java
package com.lagou.task08;
public class SubSuperTest extends SuperTest{
{
System.out.println("======SubSuperTest类中的构造块!"); // (2) e
}
static {
System.out.println("======SubSuperTest类中的静态代码块!"); // (1) b
}
public SubSuperTest(){
System.out.println("======SubSuperTest类中的构造方法体!"); // (3) f
}
public static void main(String[] args){
// 使用无参方式构造子类的对象
SubSuperTest sst = new SubSuperTest();
}
}
权限修饰符和包的定义
常用的访问控制符
注意事项
public修饰的成员可以在任意位置使用
private修饰的成员只能在本类内部使用
- 通常情况下,
成员方法
都是用public关键字修饰
,成员变量
都是用private关键字修饰
package语句的由来
- 定义类时需要指定类的名称,但如果仅仅将类名作为类的唯一标识,则不可避免的出现命名冲突的问题,这会给组件复用以及团队间的合作造成很大的麻烦!
- 在Java语言中,用包(package)的概念来解决命名冲突的问题
包的定义
-
在定义一个类时,除了定义类的名称还需要指定一个包名,格式如下:
package包名;
package 包名1.包名2.包名3.包名4…包名n;
-
为了实现项目管理、解决命名冲突以及权限控制的效果
定义包的规范
- 如果各个公司或开发组织的程序员都随心所欲的命名包名的话,仍然不 能从根本上解决命名冲突的问题。因此,在指定包名的时候应该按照一 定的规范。
- org.apache.commons.lang.StringUtil
- 其中StringUtils是类名而org.apache.commons.lang是多层包名,其含义 如下:org.apache表示公司或组织的信息(是这个公司(或组织)域名的 反写);common 表示项目的名称信息;lang 表示模块的名称信息。
包的导入
- 使用
import关键字导入包
- 使用
import关键字导入静态成员
,从java5.0开始支持
final修饰类和方法的作用
基本概念
final
本意是“最终的、不可改变的
”,可以修饰类、成员方法以及成员变量
使用方式
-
final关键字修饰类体现在该类不能被继承
主要用来防止滥用继承,如:java.lang.String类等
-
final关键字修饰成员方法体现在该方法不能被重写但可以被继承
主要用在防止不经意间造成重写,如:java.text.Dateformat类中format方法等
-
final关键字修饰成员变量体现在该变量必须初始化且不能改变
主要用于防止不经意间造成改变,如:java.lang.Thread类中MAX_PRIORITY等
FinalClass.java
package com.lagou.task08;
// ctrl + shift+ / 进行选中的多行注释,再来一次取消注释
// ctrl + / 进行当前行的单行注释,再来一次取消注释
public /*final*/ class FinalClass {
public /*final*/ void show(){
System.out.println("FinalClass类中的show方法");
}
}
SubFinalClassTest.java
package com.lagou.task08;
public class SubFinalClass extends FinalClass {
/* @Override
public void show() {
super.show();
}*/
public static void main(String[] args) {
SubFinalClass sfc = new SubFinalClass();
sfc.show();
}
}
FinalMemberTest.java
package com.lagou.task08;
public class FinalMemberTest {
// private final int cnt = 1; // 显式初始化
private final int cnt;
/*{
cnt = 2; // 构造块中进行初始化
}*/
public FinalMemberTest(){
cnt = 3; // 构造方法体中进行初始化
}
public static void main(String[] args) {
// 声明FinalMeber类型的引用指向该类的对象
FinalMemberTest fmt = new FinalMemberTest();
// 打印成员变量的数值
System.out.println("fmt.cnt = " + fmt.cnt);
}
}
final修饰成员变量的作用
常量的概念
- 在以后的开发中很少单独使用final关键字来修饰成员变量,通常使用
public static final关键字共同修饰成员变量来表达常量的含义
,常量
的命名规范要求是所有字母都要大写
,不同的单词之间采用下划线连
*public static final double PI = 3.14;
总结
1、static关键字
概念、使用方式、构造块和静态代码块、单例设计模式
、饿汉式和懒汉式等
2、 继承
概念、特点、方法的重写、重写的原则、IDEA使用等
3、访问控制
public、private、package、导入等
4、final关键字
概念、修饰类、成员方法、成员变量、常量等