一、this关键字
1、使用区域:定义类时在类的方法中使用,包括构造方法和成员方法
2、特点:表示Java程序运行时正在调用此方法的对象
3、使用范围:
(1)引用当前对象中的成员变量
典例:用于区分变量名相同的成员变量和局部变量
- 不使用this关键字,JVM会现在局部作用域查找局部变量,如果找到了,则使用所找到的变量,如果没找到,JVM会继续在成员变量作用域查找局部变量,如果找到了,则使用在成员变量作用域所找到的变量
public class Student {
private String num;
private String name;
private int age;
public Student(String num,String name,int age){
num=num;
name=name;
age=age;
}
public static void main(String[] args) {
Student student=new Student("111", "八戒",18);
System.out.println(student.num);
System.out.println(student.name);
System.out.println(student.age);
}
}
- 使用this关键字
public class Student {
private String num;
private String name;
private int age;
public Student(String num,String name,int age){
this.num=num;
this.name=name;
this.age=age;
}
public static void main(String[] args) {
Student student=new Student("111", "八戒",18);
System.out.println(student.num);
System.out.println(student.name);
System.out.println(student.age);
}
}
(2)引用当前对象中的构造方法
典例:为当前对象中的成员变量初始化默认值
public class Student {
private String num;
private String name;
private int age;
public Student(){
this("222", "沙僧",19);
}
public Student(String num,String name,int age){
this.num=num;
this.name=name;
this.age=age;
}
public static void main(String[] args) {
Student student=new Student();
System.out.println(student.num);
System.out.println(student.name);
System.out.println(student.age);
}
}
(3)引用当前对象中的成员方法
public class Student {
private String num;
private String name;
private int age;
public Student(String num,String name,int age){
this.num=num;
this.name=name;
this.age=age;
}
public void study(){
System.out.println(this.name+"学习");
this.exam();
}
public void exam(){
System.out.println(this.name+"测试");
}
public static void main(String[] args) {
Student student=new Student("333","三藏",20);
student.study();
}
}
4、注意:在一个类的定义中,方法或代码块中等号左边的变量如果加了this,则该变量为成员变量,等号左边如果没有加this,则该变量如果在该方法或代码块的作用域中定义,则该变量为局部变量,否则为成员变量
二、static关键字
1、定义
(1)static关键字表示静态,用static关键字修饰的成员是静态成员
(2)static关键字只能用来修饰类的成员变量、成员方法、代码块和内部类,不能用来修饰类的构造方法
2、特点
(1)静态成员信息与类信息(类对应的class文件/类的静态代码)一样,在内存中只有一份,都在类模版中,而类模版在JVM的方法区中
(2)静态成员与类同时加载
(3)静态成员先于对象存在
(4)静态成员被所有对象共享
(5)既可以用对象访问静态成员,也可以用类名访问静态成员,建议使用类名访问
3、静态变量
(1)定义:用static关键字修饰的成员变量就是静态变量
(2)使用时机:当类的所有对象的某个属性值性同时,则在类定义中将该成员变量定义为静态变量
举例:中国人的国籍都是中国,所以将中国人类的国籍属性用static修饰,定义为静态成员
public class Chinese {
private String name;
public static String country="中国";
public static void main(String[] args) {
System.out.println(Chinese.country);// 验证特点(3)
Chinese chinese=new Chinese();
System.out.println(chinese.country);
Chinese chinese1=new Chinese();
System.out.println(chinese1.country);//验证特点(4)
chinese.country="中国中国";
System.out.println(Chinese.country);
Chinese.country="中国中国中国";
System.out.println(chinese1.country);// 验证特点(5)
}
}
(3)内存中静态变量的位置
4、静态方法
(1)定义:使用static关键字修饰的成员方法就是静态方法
(2)特点:静态方法中只能使用静态成员,包括静态变量和静态方法
(3)使用时机:如果在某个成员方法中未使用到非静态成员,则在类定义时将此方法定义为静态方法
(4)使用范围:在本类中的方法、代码块、构造器中一定可以被调用,在其他类中可以被调用(通过对象.静态方法或类名.静态方法的方式)
(4)举例:MyMath类中的max方法未使用成员变量,print方法未使用非静态成员变量,在类定义时将这两个方法定义为静态方法
public class MyMath {
public static int count=0;
public static int max(int a,int b){
MyMath.print();// 在静态方法中使用静态方法
return a>b?a:b;
}
public static void print(){
MyMath.count++;// 在静态方法中使用静态变量
System.out.println(MyMath.count);
}
public static void main(String[] args) {
System.out.println(MyMath.max(3,4));// 在静态方法中使用静态成员
System.out.println(new MyMath().max(3,4));// 验证特点(5)
}
}
(5)注意:
- 因为静态成员与类同时加载,所以static方法内不能有this和super
- 在非静态方法中可以使用所有的成员变量
5、静态变量和静态方法在实际场景中的使用-模拟卖票
// 程序运行时,该类加载一次,在内存中只有一份,服务于某个影院的某个时间段的某场电影
public class TicketSeller {
private static int ticket=10;// 该售票类所拥有的票数是一定的,无论开了几个售票窗口,卖的都是这份票,于是将票数属性定义为静态变量
public static void sellTicket(){
TicketSeller.ticket=TicketSeller.ticket-1;// 仅访问静态变量,定义为静态方法
System.out.println("卖票方法一");
}
public static void sellTicket1(){
TicketSeller.ticket=TicketSeller.ticket-1;// 仅访问静态变量,定义为静态方法
System.out.println("卖票方法二");
}
public static void sellTicket2(){
TicketSeller.ticket=TicketSeller.ticket-1;// 仅访问静态变量,定义为静态方法
System.out.println("卖票方法三");
}
public static void main(String[] args) {
TicketSeller.sellTicket();
System.out.println("剩余票数为"+TicketSeller.ticket);
TicketSeller.sellTicket1();
System.out.println("剩余票数为"+TicketSeller.ticket);
TicketSeller.sellTicket2();
System.out.println("剩余票数为"+TicketSeller.ticket);
}
}
6、注意
(1)static关键字只能用修饰类中的成员变量、成员方法、代码块
四、代码块
1、定义:在类中定义的没有名称的方法体
2、分类:分为实例代码块和静态代码块两种
(1)实例代码块
- 定义:在对象被创建时,被JVM调用的代码块
- 语法格式:
{
任何符合语法的Java代码
}
- 特点:每次对象被创建时都会被调用
(2)静态代码块
- 定义:在类被加载时,被JVM调用的代码块
- 语法格式:
static{
任何符合语法的Java代码
}
- 只会在类被加载时调用一次,与对象是否被创建无关
3、类被加载的时刻
(1)通过类名访问静态成员时,该类会被加载
证明:
public class Demo {
public static int count=0;
public static void print(){
System.out.println("静态方法"+"、"+"静态变量="+count);
}
static {
System.out.println("静态代码块1");
}
static {
System.out.println("静态代码块2");
}
}
public class Test {
public static void main(String[] args) {
System.out.println(Demo.count);
Demo.print();
}
}
结论:该例证明了通过类名访问静态成员时该类会被加载且只会加载一次
(2) 在一个类中使用main方法,该类也会被加载
证明:
public class Demo {
public static int count=0;
public static void print(){
System.out.println("静态方法"+"、"+"静态变量="+count);
}
static {
System.out.println("静态代码块1");
}
static {
System.out.println("静态代码块2");
}
public static void main(String[] args) {
}
}
(3)在一个类的对象被创建时该类会被加载
证明:
public class Demo {
public static int count=0;
public static void print(){
System.out.println("静态方法"+"、"+"静态变量="+count);
}
static {
System.out.println("静态代码块1");
}
static {
System.out.println("静态代码块2");
}
}
public class Test {
public static void main(String[] args) {
new Demo();
new Demo();
}
}
结论:该例证明了一个类的对象被创建时该类会被加载且只会加载一次
4、对象被创建时实例代码块的执行
举例:
public class Demo {
public static int count=0;
public static void print(){
System.out.println("静态方法"+"、"+"静态变量="+count);
}
{
System.out.println("实例代码块1");
}
{
System.out.println("实例代码块2");
}
}
public class Test {
public static void main(String[] args) {
new Demo();
new Demo();
}
}
结论:该例证明了对象被创建时实例代码块会被执行且对象被创建几次则实例代码块被执行几次
5、静态代码块、实例代码块、构造方法、静态方法执行的先后顺序
举例:
public class Demo {
public static int count=0;
public static void print(){
System.out.println("静态方法"+"、"+"静态变量="+count);
}
public Demo(){
System.out.println("构造方法");
}
{
System.out.println("实例代码块2");
}
{
System.out.println("实例代码块1");
}
static {
System.out.println("静态代码块1");
}
static {
System.out.println("静态代码块2");
}
}
public class Test {
public static void main(String[] args) {
new Demo().print();
new Demo().print();
}
}
结论:
结论一:由该例可得,静态代码块、实例代码块、构造方法、静态方法的执行顺序为
(1)静态代码块
(2)实例代码块
(3)构造方法
(4)静态方法
结论二:多个同级代码块,按照类定义中的顺序依次执行
五、类定义中的成员变量与成员方法
1、成员变量
(1)非静态成员变量属于对象和类,每个对象都有一份,类中也有一份
(2)静态成员变量属于类,只有类中的一份,程序运行一次,内存中同一个类的类信息只有一份,在JVM内存中的方法区中的该类的类模版中
2、成员方法
(1)非静态成员方法,只能由对象调用,在方法体中可以使用任意的成员变量和成员方法
(2)静态成员方法,只能由对象和类名调用,在方法体中只能使用静态的成员变量和静态的成员方法
六、包
1、定义:包是Java为解决类名冲突和类文件管理难度大两个问题所引入的一种机制,用于提供类的多层命名空间,可以理解为是一个文件夹,在Java中用package关键字修饰包
2、特点:
(1)每个类属于一个特定的包,因此,类名(或者叫全类名)=包名(一个具体的类的地址)+类名简称
(2)当类名简称称为类名时,此时公式中的类名称为全类名
4、包的命名规范
在包名中,使用.号来区分包的级别,包名是小写,有四个级别
(1)第一级:表示项目类型。如com(商业项目),org(开源项目),gov(政府项目)等
(2)第二级:表示开发项目或者运行项目的公司的名称,如:sun,oracle,huawei,ali,ffyc等
(3)第三级:表示项目的名称,如bcms(业务连续性管理系统),oa(办公自动化),erp(企业资源计划),cms(内容管理系统)等
(4)第四级:表示项目功能模块的名称,如web(与前端对接),service(进行逻辑处理),dao(进行数据访问)等
5、关键字import-导入外部包中的类
(1)当在一个类中使用到其他包中的类时,需要先使用import关键字以全类名的形式将该类导进来
(2)特殊地,当在一个类中使用到java.lang包中的类时,不需要将该类导入进来
6、作用:
(1)避免多个类重名时出现问题
(2)按照功能的不同管理类
(3)控制访问权限
7、举例
(1)创建包
(2)定义类
package com.ffyc.bcms.dao;
public class Car {
private String brand;
private int price;
public Car(String brand,int price){
this.brand=brand;
this.price=price;
}
public void print(){
System.out.println(this.brand+"品牌的"+this.price+"元的车");
}
}
package com.ffyc.bcms.service;
public class Car {
private String brand;
private String color;
public Car(String brand,String color){
this.brand=brand;
this.color=color;
}
public void print(){
System.out.println(this.brand+"品牌的"+this.color+"车");
}
}
package com.ffyc.bcms.web;// 标识了该Test类所在的包
import com.ffyc.bcms.service.Car;// 在Test类中使用到了其他包中的类Car,因此要将该Car类的全类名导入到该文件中来
public class Test {
public static void main(String[] args) {
new Car("宝马","红色").print();
}
}
(3)当在其他类中要使用到两个不同包中类名相同的类时,只能有一个类导入全类名之后以类名进行使用,另一个类必须以以全类名进行使用
package com.ffyc.bcms.web;// 标识了该Test类所在的包
import com.ffyc.bcms.service.Car;// 在Test类中使用到了其他包中的类Car,因此要将该Car类的全类名导入到该文件中来
public class Test {
public static void main(String[] args) {
new Car("宝马","红色").print();
new com.ffyc.bcms.dao.Car("奔驰", 66).print();
}
}