一、static关键字
案例题目:
- 编程实现People类的封装,特征有:姓名、年龄、国籍,要求提供打印所有特征的方法。
- 编程实现PeopleTest类,main方法中使用有参方式构造两个对象并打印。
/*
案例题目: 封装类
1、编程实现People类的封装,特征有:姓名、年龄、国籍,要求提供打印所有特征的方法。
2、编程实现PeopleTest类,main方法中使用有参方式构造两个对象并打印。
*/
public class People {
private String name; //声明私有成员变量描述人的姓名
private int age; //声明私有成员变量描述人的年龄
private String nationality;//声明私有成员变量描述人的国籍
public People() {} //当要求写有参构造方法时,默认要求写一个无参构造方法
//自定义有参构造参数
public People(String name, int age, String nationality) {
setName(name);
setAge(age);
setNationality(nationality);
}
//提供公有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 getNationality() {
return nationality;
}
public void setNationality(String nationality) {
this.nationality = nationality;
}
//自定义成员方法,打印所有的特征
public void show() {
System.out.println("我叫" + getName() + ",今年" + getAge() + ",来自" + getNationality());
}
}
/*
编程实现People类的测试 测试类
*/
public class PeopleTest {
public static void main(String[] args) {
//声明一个People类型的引用指向该类型的对象
People p1 = new People("赵云", 23, "蜀国");
p1.show();
People p2 = new People("司马懿", 25, "魏国");
p2.show();
}
}
1、static关键字的基本概念
- 使用static关键字修饰成员变量表示静态的含义,此时成员变量由对象层级提升为类层级,也就是整个类只有一份并被所有对象共享,该成员变量随着类的加载准备就绪,与是否创建对象无关。
- static关键字修饰的成员可以使用引用.的方式访问,但推荐类名.的方式。
/*
案例题目: 封装类
1、编程实现People类的封装,特征有:姓名、年龄、国籍,要求提供打印所有特征的方法。
2、编程实现PeopleTest类,main方法中使用有参方式构造两个对象并打印。
*/
public class People {
private String name; //声明私有成员变量描述人的姓名
private int age; //声明私有成员变量描述人的年龄
//private String nationality;//声明私有成员变量描述人的国籍 隶属于对象层级,每个对象独立拥有一份
//public static String nationality;//隶属于类层级。整个类只有一份被所有对象共享
private static String nationality;//隶属于类层级。整个类只有一份被所有对象共享
//自定义有参构造参数
People(String name, int age, String nationality) {
setName(name);
setAge(age);
setNationality(nationality);
}
//提供公有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("您输入的年级有误!");
}
}
//nationality 被声明为公有
/*public String getNationality() {
return nationality;
}*/
//nationality 被声明为私有
public static String getNationality() {
return nationality;
}
public static void setNationality(String nationality) {
//this.nationality = nationality;
People.nationality = nationality;
}
//自定义成员方法,打印所有的特征
public void show() {
System.out.println("我叫" + getName() + ",今年" + getAge() + ",来自" + getNationality());
}
}
/*
编程实现People类的测试 测试类
*/
public class PeopleTest {
public static void main(String[] args) {
//验证static修饰的静态成员(类成员)是否与创建对象无关
//nationality 被声明为公有
//System.out.println("获取到的国籍是:" + People.nationality);
//nationality 被声明为私有
System.out.println("获取到的国籍是:" + People.getNationality());
//声明一个People类型的引用指向该类型的对象
People p1 = new People("赵云", 23, "蜀国");
p1.show();
People p2 = new People("司马懿", 25, "魏国");
p2.show();
System.out.println("-------------------");
//验证static修饰的静态成员(类成员)是否被所有对象共享。
//nationality 被声明为公有
//p1.nationality = "中国";
//System.out.println("第一个成员的国籍是:" + p1.nationality);
//System.out.println("第二个成员的国籍是:" + p1.nationality);
//nationality 被声明为私有
p1.setNationality("中国");
System.out.println("第一个成员的国籍是:" + p1.getNationality());
System.out.println("第二个成员的国籍是:" + p1.getNationality());
p2.show();
}
}
2、static关键字的使用方式
-
在非静态成员方法中既能访问非静态的成员又能访问静态的成员
(成员:成员变量 + 成员方法,静态成员被所有对象共享)
-
在静态成员方法中只能访问静态成员不能访问非静态成员。
(成员:成员变量 + 成员方法,因此此时可能还没有创建对象)
-
在静态成员方法中没有this关键字,因为可以通过类名.方式调用
-
在以后的开发中只有隶属于类层级并被所有对象共享的内容才可以使用static关键字修饰。(不能滥用static关键字)
/*
编程实现static关键字的使用
*/
public class StaticTest {
private int cnt = 1; //隶属于对象层级,也就是每个对象都独立拥有一份
private static int snt = 2;//隶属于类层级,也就是所有对象都共享一份
//自定义非静态成员方法
public void show() {
//在非静态成员方法中既能访问非静态的成员又能访问静态的成员
//(成员:成员变量 + 成员方法,静态成员被所有对象共享)
System.out.println("cnt = " + cnt);// 1
System.out.println("snt = " + snt);// 2
}
public static void test() {
//System.out.println("cnt = " + cnt);// 错误: 无法从静态上下文中引用非静态变量 cnt
//System.out.println("snt = " + this.snt);//错误: 无法从静态上下文中引用非静态变量 this
System.out.println("snt = " + snt);// 2
}
public static void main(String[] args) {
StaticTest st = new StaticTest();
st.show();
System.out.println("---------------");
StaticTest.test();
}
}
3、构造块和静态代码块
- 构造块:在类体中直接使用{}括起来的代码块
- 每创建一个对象都会执行一次构造块
- 静态代码块:使用static关键字修饰的构造块
- 静态代码块随着类的加载时执行一次
/*
编程实现构造块和静态代码块的使用
*/
public class BlockTest {
//当需要在执行构造方法体之前做一些准备工作时,则将准备工作的相关代码写在构造块中
//比如对成员变量进行的统一初始化操作
//只要创建对象就会执行一次
{//在静态代码块之后执行
System.out.println("构造块!");
}
//静态代码块会随着类的加载而准备就绪,会先于构造块执行,但只会执行一次
//当需要在执行代码块之前随着类的加载做一些准备工作时,则编写代码到静态代码块中
//比如:加载数据库的驱动包等
static {//最先执行
System.out.println("静态代码造块!");
}
//自定义构造方法 最后执行
public BlockTest() {
System.out.println("构造方法体!");
}
public static void main(String[] args) {
BlockTest bt = new BlockTest();
BlockTest bt2 = new BlockTest();
/*
输出:
静态代码造块!
构造块!
构造方法体!
构造块!
构造方法体!
*/
}
}
4、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.print(args[i]); System.out.print(" "); if((i +1) % 5 == 0) { System.out.println(); } } } }
二、单例设计模式
1、单例设计模式的概念
- 在某些特殊的场合中,一个类对外提供且只提供一个对象时,这样的类叫做单例类,而设计单例的流程和思想叫做单例设计模式
2、单例设计模式的实现流程
- 私有化构造方法,使用private关键字修饰
- 声明本类类型的引用指向本类类型的对象,并使用private static关键字共同修饰
- 提供公有的get方法负责将对象返回出去,并使用public static关键字共同修饰
3、单例设计模式的实现方式
- 单例设计模式的实现方式有两种:饿汉式和懒汉式,在以后的开发中推荐饿汉式。
/*
编程实现Singleton类的封装
*/
public class Singleton {
////饿汉式 在开始代码一运行就创建对象
//声明Singleton类型的引用指向该类型的对象,使用private static关键字共同修饰
private static Singleton sin = new Singleton();
//私有化构造方法,用private关键字修饰
private Singleton() {}
//提供公有的get、set方法,将对象返回出去,使用public static关键字共同修饰
//当类对外能且只能提供一个对象时,用getInstance表示通过这个方法只能得到类的一个实例和对象
public static Singleton getInstance() {//Instance表示实例
return sin;
}
/*
//懒汉式 调用getInstance方法时创建对象
private static Singleton sin = null
//私有化构造方法,用private关键字修饰
private Singleton() {}
//提供公有的get、set方法,将对象返回出去,使用public static关键字共同修饰
//当类对外能且只能提供一个对象时,用getInstance表示通过这个方法只能得到类的一个实例和对象
public static Singleton getInstance() {//Instance表示实例
if(null == sin) {
sin = new Singleton();
}
return sin;
}
*/
}
/*
编程实现Singleton类的测试
*/
public class SingletonTest {
public static void main(String[] args) {
//声明一个Singleton类型的引用指向该类型的对象
//Singleton s1 = new Singleton();
//Singleton s2 = new Singleton();
//System.out.println(s1 == s2);
//Singleton.sin = null; 可以使得引用对象无用
//Singleton.set(null);
//Singleton.setInstance(People);
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2);
System.out.println(S1);
System.out.println(S2);
}
}
三、继承
1、继承的概念
-
当多个类之间有相同的特征和行为时,可以将相同的内容提取出来组成一个公共类,让多个类吸收公共类中已有特征和行为而在多个类型中只需要编写自己独有特征和行为的机制,叫做继承。
-
在Java语言中使用extends(扩展)关键字来表示继承关系。
如:
public class Worker extends Person{} -表示Worker类继承自Person类
其中Person类叫做超类、父类、基类。
其中Worker类叫做派生类、子类、孩子类。
-
使用继承提高了代码的复用性,可维护性及扩展性,是多态的前提条件。
/*
编程实现Person类的封装
*/
public class PersonF {
//私有化成员变量,使用private关键字修饰
private String name;
private int age;
//在构造方法中调用set方法进行合理值的判断
public PersonF() {}
public PersonF(String name, int age) {
setName(name);
setAge(age);
}
//提供公有的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 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类继承自PersonF类
*/
public class Worker extends PersonF {
}
/*
编程实现Worker类的测试
*/
public class WorkerTest {
public static void main(String[] args) {
//使用无参方式构造Worker类型的对象并打印特征
Worker w = new Worker();
w.show();
w.eat("米饭");
}
}
/*
编程实现Teacher类继承自PersonF类
*/
public class Teacher extends PersonF {
}
/*
编程实现Teacher类的测试
*/
public class TeacherTest {
public static void main(String[] args) {
Teacher t1 = new Teacher();
t1.show();
t1.eat("饺子");
t1.play("QQ飞车");
}
}
2、继承的特点
- 子类不能继承父类的构造方法和私有方法,但私有成员变量可以被继承只是不能直接访问
- 无论使用何种方式构造子类的对象时都会自动调用父类的无参构造方法,来初始化从父类中继承的成员变量,相当于在构造方法的第一行增加代码super()的效果。
- 使用继承必须满足逻辑关系:子类 is a 父类,也就是不能滥用继承。
- Java语言中只支持单继承不支持多继承,也就是说一个子类只能有有一个父类,但是一个父类可以有多个
/*
编程实现Person类的封装
*/
public class PersonF {
//私有化成员变量,使用private关键字修饰
private String name;
private int age;
//在构造方法中调用set方法进行合理值的判断
public PersonF() {
System.out.println("Person()");
}
public PersonF(String name, int age) {
System.out.println("Person(String, int)");
setName(name);
setAge(age);
}
//提供公有的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 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类继承自PersonF类
*/
public class Worker extends PersonF {
private int salary;
/*
* 无论使用何种方式构造子类的对象时都会自动调用父类的无参构造方法,
* 来初始化从父类中继承的成员变量,
* 相当于在构造方法的第一行增加代码super()的效果。
*/
public Worker() {
super();//表示调用父类的无参构造方法,若没有加则编译器自动添加。
System.out.println("Worker()");
}
public Worker(String name, int age, int salary) {
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 show() {
System.out.println("我是" + getName() + ",今年" + getAge() + "岁,我的薪水是:" + getSalary());
}
//自定义成员方法描述工作的行为
public void work() {
System.out.println("今天的砖有点烫手!!!");
}
}
/*
编程实现Worker类的测试
*/
public class WorkerTest {
public static void main(String[] args) {
//使用无参方式构造Worker类型的对象并打印特征
Worker w1 = new Worker();
w1.show();
System.out.println("--------------------------");
Worker w2 = new Worker("张飞", 30, 5000);
w2.show();
w2.eat("米饭");
w2.play("王者荣耀");
w2.work();
}
}
四、方法重写
1、方法重写的概念
- 从父类中继承下来的方法不满足子类的需求时,就需要在子类中重写一个和父类一样的方法来覆盖从父类中继承下来的版本,该方法就叫做方法的重写(Override)。
//自定义show方法覆盖从父类中继承的版本
@Override //标注/注解 用于说明下面的方法时对父类的方法重写,若没有构成重写则编译报错
public void show() {
super.show();
System.out.println("我的薪水是:" + getSalary());
//System.out.println("我是" + getName() + ",今年" + getAge() + "岁,我的薪水是:" + getSalary());
}
2、方法重写的原则
- 要求方法名相同、参数列表相同以及返回值类型相同,从Java5开始允许返回子类类型。
- 要求方法的访问权限不能变小,可以相同或者变大
- 要求方法不能抛出更大的异常(异常机制)。
3、Java开发常用工具
-
文本编辑器(TE,Text Editor)
记事本、Notepad++、Edit Plus、UltraEdit、…
-
集成开发环境(IDE,Integrated Development Environment )
Jbuilder、NetBeans、Eclipse、MyEclipse、IDEA、
4、构造块与静态代码块(笔试)
- 先执行父类的静态代码块,在执行子类的静态代码块
- 执行父类的构造块,执行父类的构造方法体
- 执行子类的构造块,执行子类的构造方法体
package com;
public class SuperTest {
{
System.out.println("SuperTest类中的构造块");//(2)
}
static {
System.out.println("SuperTest类中的静态代码");//(1)
}
public SuperTest() {
System.out.println("SuperTest类中的构造方法体");//(3)
}
public static void main(String[] args) {
SuperTest st = new SuperTest();
}
}
package com;
public class SubSuperTest extends SuperTest {
{
System.out.println("======SubSuperTest类中的构造块");//(2)
}
static {
System.out.println("======SubSuperTest类中的静态代码");//(1)
}
public SubSuperTest() {
System.out.println("======SubSuperTest类中的构造方法体");//(3)
}
public static void main(String[] args) {
SubSuperTest st = new SubSuperTest();
}
}
/*
输出:
SuperTest类中的静态代码
======SubSuperTest类中的静态代码
SuperTest类中的构造块
SuperTest类中的构造方法体
======SubSuperTest类中的构造块
======SubSuperTest类中的构造方法体
*/
五、访问控制
1、常用的访问控制符
修饰符 本类 同一包中的类 子类 其他类
public 可以访问 可以访问 可以访问 可以访问
protected 可以访问 可以访问 可以访问 不能访问
默认 可以访问 可以访问 不能访问 不能访问
private 可以访问 不能访问 不能访问 不能访问
2、注意事项
- public修饰的成员在任意位置使用
- private修饰的成员只能在本类内部使用
- 通常情况下,成员方法都是用public关键字修饰,成员变量都使用private关键字修饰
3、package语句的由来
- 定义类时需要指定类的名称,但如果仅仅将类名作为类的唯一标识,则不可避免的出现命名冲突的问题。这回给组件复用以及团队间的合作造成很大的麻烦。
- 在Java语言中,用包(package)的概念来解决命名冲突的问题。
4、包的定义
-
在定义一个类时,除了定义类的名称一般还要指定一个包名,格式如下:
package 包名;
package 包名1.包名2.包名3...包名n;
-
为了实现项目管理、解决命名冲突以及权限控制的效果。
5、定义包的规范
- 如果各个公司或者开发组织的程序员都随心所欲的命名包名的话,任然不能从根本上解决命名冲突的问题。因此,在指定包名的时候应该按照一定的规范。
- org.apache.commons.lang.StringUtil
- 其中StringUtil是类名而org.apache.commons.lang是多层包名,其中含义如下:org.apache表示公司或者组织的信息(是这个公司或者组织域名的反写);common表示项目的名称信息;lang表示模块的名称信息。
6、包的导入
- 使用import关键字导入包
- 使用import关键字导入静态成员,从Java5.0开始支持。
六、final关键字
1、final关键字的基本概念
- final本意为“最终的、不可改变的”,可以修饰类、成员方法以及成员变量。
2、使用方式
-
final关键字修饰类体现在该类不能被继承。
- 主要用于防止滥用继承,如:java.lang.String类等
-
final关键字修饰成员方法体现在该方法不能被重写但可以被继承。
- 主要用于防止不经意间造成重写,如:java.text.Dataformat类中format方法等。
-
final关键字修饰成员变量体现在该变量必须初始化且不能改变
- 主要用于防止不经意间造成改变,如:java.lang.Thred类中MAX_PRIORTTY等。
3、常量的概念
-
在以后的开发中很少单独使用final关键字来修饰成员变量,通常使用public static final关键字共同修饰成员变量来表达常量的含义,常量的命名规范要求所有字母都要大写,不同的单词之间采用下划线连接。
-
public static final double PI = 3.14.
文章内容输出来源:拉勾教育Java高薪训练营