Java类的定义
人以类聚,物以群分,Java 类把某些具体的相似的实体,总结抽象出描述这些具体实体的属性,和行为。比如人类,从很多的具体的人,老人,小孩等等总结,抽象出来的。当你给火星人谈“人类”的时候,他可能一脸懵逼,但你说人类的代表就像你这样的,他可能就秒懂了,这说明类是抽象的。只有具体到实例,才能具体的了解类。
Java面向对象的三大特征: 封装、继承、多态。
-
定义格式
class 类名{ 声明成员变量; 声明成员方法; }
-
命名规范
1、第一个字母要大写;
2、“见名知意”,名字有一定的意义,Student、Person、Car
3、名字中具有一定功能性的描述,如OrderService,StudentManager
类定义案例
public class Demo{
public static void main(String[] args) {
People people = new People();
people.name = "楼主";
people.eat();//楼主正在吃
}
}
//这也说明一个.java文件能有多个类
class People {
String name;
public void eat() {
System.out.println(this.name + "正在吃");
}
}
图解
局部变量与成员变量的区别
局部变量: 随着方法入栈初始化,随着方法出栈而消失
成员变量: 随着对象的初始化创建,随着对象的回收而消失
案例
public class Demo {
public static void main(String[] args) {
Student student = new Student();
student.name = "萌萌";
student.age = 18;
student.say();//1今年萌萌18岁
student = null;//person指向的堆内存会被垃圾回收器(GC)回收
}
}
class Student {
String name;
int age;
public void say() {
int id = 1;
System.out.println(id + "今年" + name + age+"岁");
}
}
java 访问权限
-
成员的四个访问权限
private 私有的,只能在类的内部访问
[default] 默认的,可以在同一个包下访问
protected 受保护的,可以在类的内部和子类中访问
public 公有的,可以在任一地方访问
-
this 关键字
this: 指向当前类对象,当出现局部变量与成员变量重命名时,需要使用this来访问成员变量。
案例
public class Demo {
public static void main(String[] args) {
Person person=new Person(); //调用了默认的构造方法(无参的)
//stu.name="张三"; //私有的成员是不能通过对象访问
person.setName("张三");
person.setAge(30);
person.sex="女";
System.out.println("Person: "+person.toString());//Person: [name=张三,age=30,sex=女]
}
}
class Person { //数据实体类
private String name; //默认值为null
private int age; //默认值为0
String sex = "男";
//方法名的命名方式为驼峰命名方法(setXxx,getXxx)
public void setName(String name) {
this.name = name; //this.name代表的是成员变量
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
//实现将对象转成字符串的方法
public String toString() {
return "[name=" + name + ",age=" + age + ",sex=" + sex + "]";
}
}
如图
| 修饰符 | 当前类 | 同包 | 子类 | 其他包 |
| ------------- |:-------------:|: -----:|:-----------:|-------:|
| public | 可以 | 可以 | 可以 | 可以 |
| protected | 可以 | 可以 | 可以 | 不可以 |
| 默认(friendly) | 可以 | 可以 | 不可以 | 不可以 |
| private | 可以 | 不可以 |不可以 | 不可以 |
类的构造方法
构造方法的作用,初始化成员变量,也是了解一个类的入口。
-
定义格式
public 类名(){}且无返回值
-
注意的点
1、构造方法只能用于初始化对象,不能被对象调用和类的成员方法中调用
2、 默认构造方法为无参的,也是隐式构造方法(无需提供)
3、 可以提供有参的构造方法,但会覆盖默认的构造方法 在初始化时,必须显示使用构造方法
4、 两个构造方法之间可以相互调用,使用this()方式调用,但必须在第一行。
构造函数案例
public class Demo{
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.say();
Teacher xiao = new Teacher("小小");
xiao.say();
//匿名对象:不存在一个引用指向这个对象
new Teacher("shabi").say(); //当执行完成后,对象空间可以被垃圾回收器回收
}
}
class Teacher { //动物类
private String name;
public Teacher() { //无参的构造方法
this("teacher"); //调用有参的构造方法,必须在第一行
//name="teacher";
}
public Teacher(String name) { //带有参数的构造方法,默认情况下会覆盖无参的构造方法
this.name = name;
}
public void say() {
System.out.println("大家好,Teacher,我叫 " + name);
}
}
static 关键字
-
static 修饰的成员是静态成员变量。它有以下特点:
1、 随着类的加载,会在方法区的静态区中开辟内存空间,初始化数据
2、 可以通过类名直接访问,格式:类名.静态成员变量
3、 一般用于存储所有类的共享数据
-
静态成员方法,特点:
1、静态方法中只能访问静态成员(不能使用this引用)
2、非静态方法中可以访问静态成员(都能访问)
-
静态成员变量与非静态成员变量的区别
1、 生命周期
静态成员变量随着类的加载,在方法区的静态区中初始化,在程序结束时而消失;成员变量是随着对象的初始化,在堆中创建与初始化,在对象被垃圾回收时而消失。
2、存储的特点
静态成员变量是所有对象共享存储的数据;成员变量是某一对象存储的数据。
3、访问方式
静态成员变量可以通过类名直接访问,也可以对象访问;成员变量只能通过对象来访问。
static案例
public class Demo {
public static void main(String[] args) {
Student1.sex="男"; //直接通过类名来访问类中的静态成员变量
Student1 s1= new Student1();
s1.setAge(30);
s1.say();//hello,女,30
s1.sex="不男不女"; //也可以通过类的对象访问类中的静态成员变量
s1.say();//hello,女,30
Student1 s2=new Student1();
s2.setAge(25);
s2.say();//hello,女,25
}
}
class Student1{
static String sex="男"; //静态成员变量
private int age;
public void setAge(int age){
this.age=age;
}
public static void setSex(String sex){//静态成员方法
Student1.sex=sex;//将方法中的局部变量的值 赋给静态成员变量
//age=30; //在静态方法中不能访问非静态成员
}
public void say(){ //在成员方法中,是否可以访问静态成员变量
setSex("女"); //在非静态方法中可以访问静态方法
System.out.println("hello,"+sex+","+age);
}
}
静态代码块,构造代码块
静态代码块
static{ }
主要作用:初始化静态成员变量,随着类的加载而执行的,只执行一次。
构造代码块
{ code...}
优先于构造方法执行,主要是来初始化成员变量,随着对象的创建而执行,每次创建对象都会执行。
static修饰符什么时候使用?
1、 在多个类之间共享成员变量时,需要将其改为static静态成员变量
2、 如果一个成员方法中没有访问本类的成员变量,则将其改为static静态成员方法
注:在程序优化中,建议不要过多地使用static,因为它会长时间地保留在内存中(方法区的静态区)
有静态代码块,构造代码块时,对象的初始化过程
1、加载类的字节码文件到jvm的方法区中
2、为静态成员变量在静态区开辟内存空间,并初始化默认值
3、加载静态代码块,初始化静态成员变量
4、在堆中开辟空间(根据成员变量的大小),并默认初始化成员变量
5、加载构造代码块,显示初始化成员变量
6、加载构造方法,显示初始化成员变量
7、将堆内存空间的首地址赋给对象的引用
静态代码块,构造代码块案例
public class Demo{
public static int age;
static {
System.out.println("静态代码块age-->" + age);
//初始化静态成员变量,在类加载时执行
age = 20;
System.out.println("静态代码块age-->" + age);
}
{ //构造代码块,可以被看成是一个无参的构造方法
age += 1;
System.out.println("构造代码块-->" + age);
}
public Demo() {
age += 1;
System.out.println("构造方法中: age-->" + age);
}
public static void main(String[] args) {
new Demo();
new Demo();
new Demo();
new Demo();
}
}
运行结果
类的继承
关键字 extends,通过继承,可以将父类的成员继承过来,使得两个存在父子关系
案例
public class Demo {
public static void main(String[] args) {
Person1 person1 = new Person1();
person1.setName("小李子");
person1.eat();//小李子,正在吃
Student2 s2 = new Student2();
s2.setName("贱人曾");
s2.eat();//贱人曾,正在吃
Worker worker = new Worker("xiaofeifei");
worker.eat();//xiaofeifei,正在吃
}
}
class Person1 { //父类
private String name;
public Person1() {
} //无参的构造方法
public Person1(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + ",正在吃");
}
}
class Student2 extends Person1 { //子类
}
class Worker extends Person1 { //子类
public Worker(String name) {
super(name); //调用父类的构造方法,super()必须在第一行
}
}
继承中的构造、静态代码块
继承中的类成员特点
1、父类的私有成员不能被访问
2、如果子类中存在成员与父类的成员重名,则使用super来访问父类中同名成员,super是代表父类的数据空间,并不是一个对象
继承中有静态代码块,构造代码块时,对象的初始化过程
1、父类的静态代码块
2、子类的静态代码块
3、父类的构造代码块。。
4、父类构造方法-->初始化父类的成员变量
5、子类的构造代码块。。
6、子类构造方法-->初始化子类的成员变量
案例
public class Demo {
public static void main(String[] args) {
Child c1 = new Child();
c1.say();
}
}
class Parent {
private String name;
public int age;
static {
System.out.println("父类的静态代码块。。");
}
{
System.out.println("父类的构造代码块。。");
}
public Parent() {
System.out.println("父类构造方法-->初始化父类的成员变量");
}
private void setName(String name) {
}
public void talk() {
System.out.println("父类 age:" + age);
}
}
class Child extends Parent { //子类,继承父类的所有成员
private int age;
static {
System.out.println("子类的静态代码块。。");
}
{
System.out.println("子类的构造代码块。。");
}
public Child() {
System.out.println("子类构造方法-->初始化子类的成员变量");
}
public void say() {
//name="张三";//出错,父类的私有成员不能被访问
//setName("张三");//同上
super.age = 100; //访问父类的成员变量
age = 90; //访问子类的成员变量
System.out.println("子类 age:" + age);
talk(); //非私有成员方法都能访问
}
}