回顾
面向编程思想:所有事物触发的原则是对象,找到这个对象身上具备的【属性和行为】,描述对象需要通过类,类中就定义着属性和行为【成员变量和成员方法】,如果要通过类构建对象,就需要提供对象构造方法,构造方法分为常用的两种,一种是无参构造方法【方法的参数列表中没有任何参数】,另外一种是有参构造方法【方法参数列表中定义参数,原则是类中有哪些成员变量,形参列表就和成员变量一致,还可以选择性的提供初始化变量】,类中构造方法是允许重载的
如何在代码中创建类和对象
1.创建类
访问权限修饰符 class 类名{
成员变量 --> 对象的属性
构造方法 --> 对当前创建对象的一种方式,除了创建对象之外,还可对属性进行初始化
成员方法 --> 对象的行为
}
2.创建对象
类名 对象名 = new 类名();
PS: new 后面 类名() 其实就是在调用构造方法
3.如何在类中定义构造方法
3.1 无参构造方法
public 类名(){
对属性进行初始化操作,所有调用无参构造方法对象,都会有这个默认属性赋值
调用一些其他方法,这样做比较少
还可以this关键字和Super关键字
}
public 类名(和属性类型一致的参数列表){
对属性进行初始化操作,根据创建对象的不同动态的存储每个不同对象属性初始值
调用一些其他方法,这样做比较少
还可以this关键字和Super关键字
}
PS: 如果类中没有明确的提供构造方法, 系统会默认提供一个午无参构造方法
如果类中明确提供构造方法,此时系统提供的无参构造将不能再调用
4.成员变量和成员方法
类中定义成员变量其实就是之前的【全局变量】,成员变量可以使用权限修饰符,有默认值,默认值和数据类型有关
类中定义成员方法其实就是原有静态方法 去掉static
访问权限修饰符 返回值类型 方法名(参数列表){
方法体
return
}
PS: 成员变量和成员方法是够可以添加static关键字?
是可以的,但是含义完全变了,添加了static关键字之后会成为类属性和类方法,而不是单独属于某一个对象
所以如果明确是成员变量和成员方法,就不要添加static关键字。
如何调用成员变量和成员方法?
调用成员变量 --> 对象名.成员变量名
调用成员方法 --> 对象名.成员方法名()
PS: 这种调用方式是因为,不在描述类中,是在另外一个类中调用
作业
package com.qfedu.HomeWork;
//狗类狗具有属性(姓名,年龄,性别,种类)和行为(吃,喝,咬人)
//对类进行了一个区分:描述对象的 --》这个类就是描述类或实体类 --》 这个类中是不写main方法
public class Dog {
//定义对象属性 --> 成员变量
String name;
int age;
char gender;
String kind;
//提供外部创建Dog类对象的方式 --》 构造方法
public Dog(){}
//形参的类型和属性的类型,形参顺序和属性顺序是一致
public Dog(String n,int a,char g,String k){
//通过形参对实行属性进行赋值
name = n;
age = a;
gender = g;
kind = k;
}
public void eat(){
//成员变量,除了在外部【当前类之外】,需要使用对象名.属性名
//在类的内部可以直接在成员方法中使用,不需要使用任何关键字和修饰
System.out.println(name + "吃什么。。。。");
}
//喝和 咬人就可完全仿照上面这个方法定义即可
}
如果在一类中需要使用到另外一个类的属性和行为?
"第一种方式":在使用类中,将另外一个类的对象作为当前类属性存在【必须满足客观现实规律】
好处:因为是在了中定义属性即成员变量,所以可以直接在整个类中使用【使用范围广泛】
坏处:需要满足客观现实规律
设计一个电脑类, 属性: CPU, 主板, 硬盘, 内存, 显卡
CPU/主板/硬盘/内存/显卡 都是单独的类, 属性: 名称/价格
电脑类方法: 计算这个电脑的价格
package com.qfedu.HomeWork;
public class CPU {
String name;
int price;
public CPU(){
}
public CPU(String n, int p){
name = n;
price = p;
}
}
public class Xianka {
String name;
int price;
public Xianka(){
}
public Xianka(String n, int p){
name = n;
price = p;
}
}
public class YingPan {
String name;
int price;
public YingPan(){
}
public YingPan(String n, int p){
name = n;
price = p;
}
}
public class Zhuban {
String name;
int price;
public Zhuban(){
}
public Zhuban(String n, int p){
name = n;
price = p;
}
}
public class NeiChun {
String name;
int price;
public NeiChun(){
}
public NeiChun(String n, int p){
name = n;
price = p;
}
}
//电脑
public class Computer {
//CPU, 主板, 硬盘, 内存, 显卡
CPU cup; //对于外部而言 CPU是一个类,对于Computer而言他是一个属性【成员变量】
//这个CPU属性就相当于是 CPU cpu = new CPU("i790000",1000);
Zhuban zb;
YingPan yp;
NeiChun nc;
Xianka xk;
public Computer(){}
public Computer(CPU c,Zhuban z,YingPan y,NeiChun n,Xianka x){
cup = c; // c = new CPU("i790000",1000)
zb = z;
yp = y;
nc = n;
xk = x;
}
public void addMoney(){
int sum = cup.price+zb.price+yp.price+nc.price+xk.price;
System.out.println("电脑的价格:"+sum);
}
}
"第二种方式":在使用类中,创建一个方法,方法的参数是需要使用类的对象【即使用类是以方法参数存在】
好处: 什么地方用就写在什么位置,并且不受客观现实规律影响
坏处: 作用域范围小【仅限当前方法内部使用】
通过构造方法,初始化一个四开门白色宝马,模拟一个场景富二代,炫耀自己的车
富二代对象 --> 行为 介绍自己的
package com.qfedu.HomeWork;
public class Car {
int door;//车门
String color;//颜色
public Car(){}
public Car(int d,String c){
door = d;
color = c;
}
}
/**
* 富二代
*/
public class Person {
String name;
public Person(String n){
name =n;
}
//Car是不能成为当前Person属性,但是又要用到car的信息
public void showInfosCar(Car car){
System.out.println(name+"在介绍自己的车:"+car.color+" "+car.door);
}
}
PS:在一个类使用另外一个类的属性或方法时,当前这两种形式叫做 --》【类的复合】
图书管理员
package com.qfedu.HomeWork2;
/**
* 图书管理员类
*/
public class LibraryManager {
//属性
String name;
public LibraryManager(){}
public LibraryManager(String n){
name = n;
}
//行为 需要限制传入参数
public String checkCardType(Student stu){
return stu.cardType == 'A' ? "《金庸全集》" : "《十万个为什么》";
}
}
package com.qfedu.HomeWork2;
/**
* 创建学生
*/
public class Student {
String name;
char cardType;
public Student(){}
public Student(String n,char ct){
name = n;
cardType = ct;
}
public void borrowBook(){
System.out.println("在一个风雨交加的夜晚"+name+"独自一个人走在去图书馆的路上.....");
}
}
小明交换牌
/*
牌的类
*/
public class Poker {
//属性 有点数 和 花色
String color; // 牌的颜色【花色】
String num;// 牌的点数【因为有 J Q K A】
public Poker(){}
public Poker(String c ,String n){
color = c;
num = n;
}
}
/**
* 手类
*/
public class Hand {
//属性
Poker poker ;//将牌作为手的属性存在【手中有牌】
String type;//分左右手
public Hand(){}
public Hand(String t,Poker p){
type = t;
poker = p;
}
//设置一个方法拿牌
public void setPoker(Poker p){
poker = p;
}
}
package com.qfedu.HomeWork2;
/*
人
*/
public class Person {
//属性 人分左右手
/*
首先Hand类对于Person而言是Person属性,本质上leftHand和rightHand都是Hand类的对象
既然是对象就可以用过leftHand这个对象.获取Hand类中成员变量和成员方法
而Hand类中 存在一个Poker类的实行即Poker类的对象
所以通过leftHand调用自身Hand类中poker属性,就可以获取到牌的颜色和点数
中type属性,就可以获取到是左手还是右手
*/
Hand leftHand;
Hand rightHand;
public Person(){
}
public Person(Hand left ,Hand right){
leftHand = left;
rightHand = right;
}
//交换牌
public void swapPoker(){
//可以先获取手上的牌
Poker leftPoker = leftHand.poker;
Poker rightPoker = rightHand.poker;
leftHand.setPoker(rightPoker);
rightHand.setPoker(leftPoker);
}
//展示牌
public void shwoInfosPoker(){
//获取手中的牌
Poker leftPoker = leftHand.poker;
Poker rightPoker = rightHand.poker;
System.out.println(leftHand.type+"手拿的牌是:"+leftPoker.color+""+leftPoker.num);
System.out.println(rightHand.type+"手拿的牌是:"+rightPoker.color+""+rightPoker.num);
}
}
public class Test {
public static void main(String[] args) {
//2.交换牌测试
//初始化牌的对象
Poker aPoker = new Poker("红桃","A");
Poker bPoker = new Poker("方片","K");
//初始化手
Hand leftHand = new Hand("左",aPoker);
Hand rightHand = new Hand("右",bPoker);
//初始化人
Person xiaoming = new Person(leftHand,rightHand);
//展示
System.out.println("-------------------------小明没有交换牌之前----------------------------");
xiaoming.shwoInfosPoker();
System.out.println("-------------------------交换牌----------------------------");
xiaoming.swapPoker();
System.out.println("-------------------------小明交换牌之后----------------------------");
xiaoming.shwoInfosPoker();
}
}
包
在某同学的电脑中有一个文件夹,文件中存储着1000部学习视频。
问题1:当前文件夹中出现相同视频名称时候,如何处理?修改名字【致命弯道1-5】
问题2:突然间,需要在1000部学习视频中找到某一部视频,忘记名字了,但是记住了内容?
提供一种管理方式,根据不同视频内容进行分类【在创建出多个文件夹】
爱情、惊悚、动作、科幻、剧情、喜剧、学习资料…存着不同视频方便进行管理
如果在开发中,加入我们有1000个源文件,同时在src中创建,就需要对其进行一个管理操作,这个管理操作就是创建【包】
包:可以用来区分【分类】不同Java源文件,以达到对源文件管理的目的,不同包中允许存在相同类名
如何定义包?
1.创建包的时候不能以【Java】开头,因为Java有安全检查机制【Java开头的包是系统API】
2.包名必须遵守标识符命名规则,不能使用关键字【可以因情况而定】,建议全部的名称小写
3.在开发中包的名称是公司域名倒写【不包括www】
例如:
www.qfedu.com 公司的域名
创建包的名字 : com.qfedu.项目名称 或 com.qfedu.模块名称
PS:包名的层级是没有限制,要有实际意义
com.qfedu.dao.domain
在windows系统中展示的形式 [当前在工程中点就是系统中路径,包名就是系统中文件夹名称]
C:\com\qfedu\dao\domain
PS: 如果公司域名有数字 例如 www.360.com
com._360
面向对象之封装
PS:封装的本质就是不对外暴露实现过程,而是提供一个调用方法,外部无需知道内部是如何实现,只需要知道如何使用即可,这种方式就已经是封装了。
需求: 1.创建一个Cat,提供属性【姓名和年龄】,在创建一个测试类Cat进行属性赋值
package com.qfedu.block;
/*
cat类,提供属性 姓名和年龄
*/
public class Cat {
String name;
// 成员变量有两个特点 一个就是可以使用权限修饰符 另外一个是有默认值
// 现在已知权限修饰符只有一个public 公有权限,代表所有的人都可进行访问【是最大权限】
// 另外一个是default默认权限--》 也叫做包【package】权限,在整个包内部都可以访问
// 任何可以使用权限修饰符的 不写权限修饰符 默认就是包权限
// 为了保证成员变量安全,不提供直接外部对成员变量的方法,可以对成员添加权限修饰符
// 最低权限 --> private 私有的 --》一旦使用这个权限修饰符,修饰仅限当前了【类中可以访问】
private int age;
public Cat(){
}
public Cat(String n, int a){
name = n;
age = a;
}
}
package com.qfedu.block;
public class CatTest {
public static void main(String[] args) {
//1.正常创建对象
Cat cat = new Cat();
//通过cat对象调用成员变量赋值和取值操作
//cat.age = 1;
//此时这样做合理吗?
/*
如果从语法角度而言,合理。因为age是int类型 即可以存储 正整数 也可以存储 负整数
如果从客观现实规律来看,不合理,因为猫是不能出现负数年龄
这里会暴露出一个问题,只要通过Cat类创建对象,就可以对age属性任意修改
外界可以对成员变量的值肆意修改,造成变量数据不安全,在实际开发中
我们是严禁外部直接调用成员变量--》此时就需要将成员变量封装起来
在java中封装特性最有利的体现就是 ---》 属性私有【成员变量私有化】
*/
cat.age = -10000;
cat.name = "小花";
System.out.println("猫的名字:"+cat.name+"猫的年龄:"+cat.age);
}
}
总结:通过private私有化权限修饰符,体现了面向对象中封装的特性,保证了成员变量不对外直接访问的途径,这样一来成员变量就安全了,但是随之而来的是对变量操作不在向以前一样方便,如果操作的时候不进行赋值,只访问但是现在也是被禁止的,如果属性私有化了如何提供合理化访问方式?
如果属性私有化如何提供对外访问操作Getter和Setter
Getter和Setter方法
因为为了保证属性安全,对属性提供限制访问权限修饰符【private】确实可以做属性无法提供对访问,但是在实际应用,如果值打印不赋值或只赋值不打印,即想打印也想赋值,私有化属性是满足封装概念,这个概念这满足了一半,剩余通过其他方式间接操作封装属性,可以使用【Getter和Setter方法】
我们是通过Getter方法获取到属性值,Setter方法是对属赋值
PS:Getter和Setter不是必须要成对出现,可以根据实际的需求,选择性提供。
Getter方法
Getter方法的主要作用【获取】当前私有属性的值
访问权限修饰符 返回值类型 方法名(){
return 对应的私有化成员变量
}
ps:
"1.一般Getter和Setter的出现主要是伴随着私有化属性出现"
"2.因为属性已经私有化,所以这类Getter方法一般是使用public 作为权限修饰符"
"3.因为Getter方法是获取私有属性值,所以必须有返回值类型,这个返回值类型取决于获取私有属性的数据类型"
"4.这个方法的名称是固定是 【get属性名】 例如: private String name -->方法名就是 getName"
PS:如果是boolean类型私有成员变量,get方法名字是 【is属性名】
"5.Getter方法一般是没有参数列表,因为他是获取值,所以不会进行参数定义并且这个模式是固定"
"6.return 必须写,因为有返回值类型,除此之外Getter是获取属性"
Setter方法
Setter方法的主要作用是对【属性进行赋值】私有属性
访问权限修饰符 void 方法名(参数列表){
使用参数列表中形参对私有化成员变量进行赋值
}
PS:
"1.一般Getter和Setter的出现主要是伴随着私有化属性出现"
"2.因为属性已经私有化,所以这类Setter方法一般是使用public 作为权限修饰符"
"3.因为Setter方法是对私有属性赋值,所以没有返回值类型即void,并且是这个是固定的"
"4.这个方法的名称是固定是 【set属性名】 例如: private String name -->方法名就是 setName,boolean类型不受影响"
"5.必须有参数列表,参数列表中定义形参与要赋值的私有属性是一致"
"6.Setter方法是没有return关键字,也不建议添加"
注意:现在属性是私有化的,外部是无法直接访问,只要提供了getter和setter方法之后才能个对实行进行操作,获取属性值没有什么问题,但是开放赋值后,还会出现赋值错误, 例如age赋值为-1 ,这样一来封装性就没有了,此时应对策略【非法拦截】,在setter方法中对要赋值的属性进行非法拦截操作,以到大属性安全目的。
package com.qfedu.block;
/*
cat类,提供属性 姓名和年龄
*/
public class Cat {
String name;
// 成员变量有两个特点 一个就是可以使用权限修饰符 另外一个是有默认值
// 现在已知权限修饰符只有一个public 公有权限,代表所有的人都可进行访问【是最大权限】
// 另外一个是default默认权限--》 也叫做包【package】权限,在整个包内部都可以访问
// 任何可以使用权限修饰符的 不写权限修饰符 默认就是包权限
// 为了保证成员变量安全,不提供直接外部对成员变量的方法,可以对成员添加权限修饰符
// 最低权限 --> private 私有的 --》一旦使用这个权限修饰符,修饰仅限当前了【类中可以访问】
private int age;
//getter和setter方法
//获取方法---》 getter
public int getAge(){
return age;
}
//对属性赋值 ---》setter
public void setAge(int age){
if(age >= 0) {
//编译阶段是通过的,执行阶段也能过
//但是如果这样写,age并没有发生改变,此时形参名和属性名一致
//编写赋值语句的时候 age = age 发生一个就近原则 【当前变量离谁最近就是谁】
//即当前这个两个age其实都是形参,不会给属性赋值的
//此时就需要避免形参名和属性名一致,一般为了提示操作方法的人员参数是什么,参数名【变量】都会
//起的有意义,有没有什么办法可以让形参名和属性名一致并且可以赋值
//有处理方案,这个方法也是这个关键字唯一的作用 ,这个关键字就是this
this.age = age;
}else{
System.out.println("赋值参数不合法!");
}
}
public Cat(){}
public Cat(String n, int a){
name = n;
age = a;
}
}
package com.qfedu.block;
public class CatTest {
public static void main(String[] args) {
//1.正常创建对象
Cat cat = new Cat();
//通过cat对象调用成员变量赋值和取值操作
//cat.age = 1;
//此时这样做合理吗?
/*
如果从语法角度而言,合理。因为age是int类型 即可以存储 正整数 也可以存储 负整数
如果从客观现实规律来看,不合理,因为猫是不能出现负数年龄
这里会暴露出一个问题,只要通过Cat类创建对象,就可以对age属性任意修改
外界可以对成员变量的值肆意修改,造成变量数据不安全,在实际开发中
我们是严禁外部直接调用成员变量--》此时就需要将成员变量封装起来
在java中封装特性最有利的体现就是 ---》 属性私有【成员变量私有化】
*/
//cat.age = -10000;
//如果对属性进行赋值,需要使用setter
cat.setAge(-1);
cat.name = "小花";
//在外部调用时候是直接调用 get方法获取属性,而非直接操作属性
System.out.println("猫的名字:"+cat.name+"猫的年龄:"+cat.getAge());
}
}
总结:
在创建一个类需要使用如下方式完成
public class 类名{
private 成员变量
有参和无参构造方法
需要提供需求中所需要的getter和setter方法【固定全写】
成员变量
}
思考问题:创建一个功能(方法)保存所有联系人的信息
void save(String name,int age,String phoneNumber,String email,String QQNumber...)
因为当前方法可以用来保存联系人,但是随着信息的越来越多,我们参数将会越来越长,不好管理,需要传递信息过多,此时我们是不是可以将联系人信息看做时一个整体,进行的统一的管理,当前我们只需要对联系人信息进行一个统一的存储封装,只需要提供联系人信息就可以传递这个参数了,可将这个参数封装到类中,
class LinkMan{
String name;
int age;
String phoneNumber;
String email;
String QQNumber;
}
void save(LinkMan man)
封装的概念:
封装是面向三大特征之一:主要作用就是将**【信息隐藏】起来,把不需要外界知道信息隐藏,尽可能隐藏对象功能实现的细节,向外直接提供可以访问的方法,保证外界无法破坏内部的信息,这就是【封装】**
this关键字
PS: this关键字代表的式【当前对象】–》【谁调用谁就是,谁触发属性或谁触发这个方法谁就是当前对象】
总结:this 关键字的最大作用,就是区分形参名和属性名
this 关键字可以用来在类中调用【成员变量】和【成员方法】
this 关键字调用成员变量 --- 》 【this.成员变量名】 即可以完成取值操作也可以完成赋值操作
PS:现在使用this关键字调用成员变量唯一目的就是【区分形参名和成员变量】
如果在一个方法中,没有重名的问题
this.成员变量 完全等价于 成员变量
private String name;
public void showInfosName(){
System.out.println(this.name);
//和这样写没有任何区别 ,所以this关键字可以省略不写
System.out.println(name);
}
this 关键字调用成员方法 ---》 【this.成员方法(参数列表)】
this.成员方法 和 成员方法 效果是一样
public void display(){
this.show();
//和这样写完全没有区别,所以this关键字可以省略不写
show();
}
this 关键字 可以在构造中调用另外一个构造方法,必须写在第一句,不能自己调用自己
public ThisDemo() {
//this("大家好"); //调用自己的有参构造方法,而且必须在第一句,只能在构造方法中使用
}
public ThisDemo(String n){
//this(); //调用自己的无参构造方法,而且必须在第一句,只能在构造方法中使用
name = n;
}
这个方法近乎不用,会被super关键字代替
this 关键字可以当做参数传递 谁调用谁就是这个this,传递的就是调用方法的对象
作用:写有参构造方法和set方法时,如果形参名和属性名一致,使用this关键字来区分名字即可
public ThisDemo(String name){
//this(); //调用自己的无参构造方法,而且必须在第一句,只能在构造方法中使用
this.name = name;
}
类版本方法参数传递
package com.qfedu.valueAndaddress;
/**
* 类版本的参数传递
*/
public class StudentDemo {
public static void main(String[] args) {
Student stu = new Student("李逵",30);
//值传递
System.out.println("过年前:"+stu.getName()+"年龄:"+stu.getAge());
System.out.println("----------------------------过年了------------------------------");
//过年岁数要+1
addAge(stu.getAge());//这个方法出就是典型的值传递,没有任何引用个传递在里面,相当于将存在堆空建中age的值取出拷贝复制给
//在栈中开辟空间addAge方法的形参age 此时相当于是age获取到一个副本所以,这个计算方式就是一个典型值传递,所以是无法更改的
System.out.println("过年后:"+stu.getName()+"年龄:"+stu.getAge());
//引用传递
System.out.println("过年前:"+stu.getName()+"年龄:"+stu.getAge());
System.out.println("----------------------------过年了------------------------------");
//过年岁数要+1
addAge(stu);
System.out.println("过年后:"+stu.getName()+"年龄:"+stu.getAge());
//改名
System.out.println("过年前:"+stu.getName()+"年龄:"+stu.getAge());
System.out.println("----------------------------过年了------------------------------");
changeName(stu);
System.out.println("过年后:"+stu.getName()+"年龄:"+stu.getAge());
}
// String 被称为不可变字符串 ,因为每次对字符赋值的时候都会重新创建一个新的地址
public static void changeName(String name){ //将student中name的地址出传递给了形参 String name = stu.getname()
System.out.println("形参name在没有修改之前获取的值是:"+name);
name = "李鬼";//修改原有行啊 name的地址 ,形参name改名了 但是student对象中的name没有改变
System.out.println("形参name在修改之后获取的值是:"+name);
}
public static void changeName(Student stu){
stu.setName("李鬼");
}
public static void addAge(Student stu){
int age = stu.getAge()+1;
stu.setAge(age);
}
public static void addAge(int age){
age += 1;
}
}
Static关键字
static是一个关键字,可以用来修饰变量和方法【变量不能是局部变量】
static关键字的特点:
1.static关键字修饰完的属性和方法是属于【类】的
2.static修饰的属性和方法,会随着类的加载而加载
PS:当类加载器把字节码文件加载到JVM中时,static修饰的变量和方法就已经被加载到内存中了
3.优先于对象而存在的
PS:因为对象是new出来,前提是有类,有类的时候就已经有静态属性和方法
4.static修饰变量是**【所有对象共享】**,它不属于任何一个对象,它是属于类的即所有所有对象
5.static修饰变量和方法需要使用【类名.静态变量】 和【类名.静态方法】进行调用
PS:如果在同一个类中调用,可以省略类名直接调用即可
static修饰的变量和方法
package com.qfedu.Static.varAndMethod;
/**
* 静态方法和静态属性【变量】的使用
*/
public class StaticVarAndMethod {
//静态变量可以使用权限修饰符,并且存在默认值 ,是根据不同数据类型所改变
//整数【0】 小数【0.0】 char【不可见空字符】 boolean【false】 引用类型【null】
//只能在类中定义【现阶段】
static int age;
//成员变量
String name;
//成员方法
public void display(){
System.out.println("我是成员方法");
//成员方法中是可以直接调用成员变量和其他成员方的
System.out.println(name);//成员变量
showInfos(); //成员方法
System.out.println(this.name);//还可以使用this关键字
//成员方法调用静态变量和静态方法【演示是在同一个类中,省略了类名,如果是不同类不能省略类名】
System.out.println(age);//静态变量
show();//静态方法
}
public void showInfos(){}
public static void show2(){}
//静态方法
public static void show(){
System.out.println("我是静态方法");
//静态方法中调用静态变量和静态方法
System.out.println(age);//静态变量
show2();//静态方法
//静态方法调用成员变量和成员方法
//System.out.println(name);//不能直接调用成员变量
//showInfos();//不能直接调用成员方法
//System.out.println(this.name);//this关键字也不能再静态方法中使用
//因为静态是优先于对象存在的,所有静态方法中是无法直接调用成员变量和成员方法
//如果要调用,需要使用如下方式
StaticVarAndMethod vm = new StaticVarAndMethod();
System.out.println(vm.name);
vm.showInfos();
}
}
共享变量
package com.qfedu.Static.varAndMethod;
public class Test {
public static void main(String[] args) {
//调用静态变量age并赋值
StaticVarAndMethod.age = 1;
StaticVarAndMethod vm1 = new StaticVarAndMethod();
StaticVarAndMethod vm2 = new StaticVarAndMethod();
//静态变量是所有对象共享,静态变量是不属于任何而是类的,所以不建议明确使用对象调用静态变量
//静态只有类才可以调用
System.out.println("通过vm1对象对静态变量age进行修改.....");
vm1.age = 100;
System.out.println("通过vm2对象打印静态变量age的值是:"+vm2.age);
}
}
staitc修饰的代码块
PS:静态代码块只会被执行一次,当前类创建的时候,就会被加载
什么是代码块?
在类中或方法中直接使用**【{}】**大括号括起来的就是代码块代码块分三种
1.局部代码块,直接定义在方法体中(了解)
package com.qfedu.Static.block;
/**
* 局部代码块
*/
public class InnerBlock {
public static void main(String[] args) {
int b = 20;
//局部代码块
{
//定义变量
int a = 17;
System.out.println(a);
//可以访问局部代码块外部的数据
System.out.println(b);
}
//外部是无法直接访问局部代码块变量
//System.out.println(a);
}
}
2.初始化代码块(构造代码块)直接定义在类中
PS:每次创建对象的时候都会执行这个初始化代码块
每次调用构造方法之前,都会调用这个初始化代码块
package com.qfedu.Static.block;
/**
* 构造代码块
*/
public class GoZaoBlock {
public GoZaoBlock(){
System.out.println("无参构造方法");
}
//初始化代码块
{
System.out.println("初始化代码块");
}
public static void main(String[] args) {
new GoZaoBlock();
new GoZaoBlock();
}
}
3.静态代码块就是使用staitc修饰的代码块
package com.qfedu.Static.block;
/**
* 静态代码块
*/
public class StaticBlock {
public StaticBlock(){
System.out.println("无参构造方法");
}
//初始化代码块执行次数是根据创建多少决定的
{
System.out.println("初始化代码块");
}
//静态代码块只会执行一次
static{
System.out.println("静态代码块");
}
public static void main(String[] args) {
new StaticBlock();
}
}
执行过程:
静态代码块
初始化代码块
无参构造方法
PS:静态代码块多用于在创建数据库连接时候,来读取资源文件中数据
工具类
在一个项目中会有一些通用的逻辑,会被抽取到一个类中,这个类中定义都是静态方法和静态属性,通过调用这些静态方法就可以执行对应逻辑,提供这样静态方法的类就叫做【工具类】
PS:工具类的特点,不提供对象创建,里面提供的属性和方法都是静态
已经接触过的工具类**【Arrays和Math】**
自己定义工具类的时候,要求名字必须是 XXXXXUtil 或 XXXXTools
工具类和普通类的区别:
1.工具类不同对象创建,所以构造需要私有化
2.工具类方法和属性必须是static修饰
3.工具类中不允许提供main方法
package com.qfedu.Static.Utils;
/**
* 工具类
*/
public class ArraySortUtil {
//1.工具类不允许创建对象,构造方法可以使用权限修饰符 一个public 另外一个private
private ArraySortUtil(){}
public static void sortArray(int[] arr){
for(int i =0 ;i<arr.length;i++){
for(int j = i+1 ;j<arr.length;j++){
if(arr[i] > arr[j]){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
}
}