目录
一、类的定义和使用
我们知道,Java是面向对象的语言。类的定义需要我们从对象中抽象出其属性。比如一只小狗,它有名字、有年龄、有毛色还有它吃什么东西。这些东西我们都是我们抽象出来的,我们可以通过程序来使计算机认识它。
1.1 类的定义格式
class className{
field;//字段/成员方法
method//行为/成员方法
}
class是关键字,代表它是一个类。className是你所定义类的名字。field是字段,也叫成员变量。它是描述对象属性的。而method是行为,也叫成员方法,它是描述对象行为的。
接下来,我将创建一个狗的类来作为例子:
class Dog{
public String name;
public int age;
public String color;
public void eat(){
System.out.println(name+ "吃火腿肠");
}
}
注意:1.类名使用大驼峰。
二、类的实例化
实例化就是用类的类型创建对象的过程。
class Dog{
public String name;
public int age;
public String color;
public void eat(){
System.out.println(name+ "吃火腿肠");
}
}
public class Test {
public static void main(String[] args) {
Dog dog=new Dog();
dog.name="旺财";
dog.age=3;
dog.color="black";
dog.eat();
System.out.println(dog.age+" "+dog.color+" "+dog.name);
}
}
上面就是我实例化的dog对象的例子。Dog dog = new Dog();这句话创建了一个dog,它是Dog类,它有名字,颜色,年龄,他还会吃火腿肠。
注意:1.一个类可以实例化多个对象。
2.用 . 来访问对象的属性和行为。
3.类只是一张图纸,它可以用来建造东西。但是也就仅仅是一张图纸了。只有当你实例化对象的时候,它实例化的对象才能存储一定的数据。
三、this引用
3.1 为什么要用this?
我们先看一个例子:
class Stu{
public String name;
public int age;
public void setStu(String name,int age){
name=name;
age=age;
}
public void study(){
System.out.println(name+"说:好好学习,天天向上");
}
}
public class Test {
public static void main(String[] args) {
Stu s = new Stu();
s.setStu("zhu",18);
System.out.println(s.name+" "+s.age);
s.study();
}
}
这个例子定义了一个s,想要打印学生对象的姓名和年龄,再调用了一下study方法。但是却事与愿违。
为什么没有初始化成功呢? 这是因为在Stu类中,setStu方法中形参和成员变量名相同了。当局部变量和类的成员变量重名时,根据就近原则,优先使用局部变量。因此,导致了没有初始化成功。但是只要我们加上this关键字,程序就可以正常运行。
3.2 什么是this引用?
this引用可以指引对象,当对象比较多的时候,可以使编译器不混乱。
class Dog{
public String name;
public int age;
public String color;
public void setDog(String name,String color,int age){
this.name=name;
this.age=age;
this.color=color;
}
public void eat(){
System.out.println(name+ "吃火腿肠");
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.setDog("haha","blue",10);
dog.eat();
}
}
注意:this引用的是调用成员方法的对象。
3.3 this引用的特征
1.this的类型就是哪个对象引用的就是哪个对象的类型。
2.只能在成员方法中使用。
四、对象的构造及其初始化
在前面的代码中,我们有的使用set方法定义,有的使用s.xx=xxx来定义。这样非常麻烦。因此,Java中就有了构造方法的概念。
4.1 构造方法
构造方法的名字必须和类型一样,并且在创建对象的时候,编译器会自动调用。如果没有构造方法,那么编译器会自动给一个没有参数的构造方法。在整个对象的生命周期中,只在定义对象的时候调用一次。
下面我来举个例子:
class Dog{
public String name;
public int age;
public String color;
public Dog(){
}
public Dog(String name){
this.name=name;
}
public Dog(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
public void eat(){
System.out.println(name+ "吃火腿肠");
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
Dog dog2 = new Dog("旺财",18,"blue");
System.out.println(dog2.age+" "+dog2.name+" "+dog2.color);
Dog dog3 = new Dog("haha");
System.out.println(dog3.name);
}
}
上面这个例子我定义了一个狗类。并且实例化了三个对象,这次,我们在实例化的时候就给上狗的属性。我们发现,打印出来了。这是因为,在实例化对象的时候,就调用了构造方法,如果给的是一个参数,就调用一个参数的方法。如果是三个,则调用有三个参数的方法。
注意:当你给出构造方法的时候,编辑器将不再给出无参的构造方法,只能自己定义。
这就使用了this在无参构造方法中调用三个参数的构造方法。且必须在第一行。
在有参构造方法中调用了无参构造方法,在使用this调用构造方法时,注意以下几点:
①只能在构造方法中使用this()调用其他的构造方法,不能在成员方法中使用。
②在构造方法中使用this()调用构造方法的语句必须位于第一行,而且只能出现一次。
③不能在一个类中的两个构造方法中使用this()互相调用。
4.2 默认初始化
为什么成员变量在使用时不用初始化。这是因为在new对象的时候,编译器就已经为我们初始化了。编译器需要做一下几件事:
1.检查对象类是否加载,如果没有加载则加载。
2.为对象分配空间。
3.处理并发安全问题。
4.初始化所分配的空间(初始化的值在前面我已经有提到)。
5.设置对象头信息。
6.调用构造方法,给对象中各个成员赋值
4.3就地初始化
就地初始化就是在创建成员变量的同时就进行初始化。例子如下:
class Dog{
private String name="旺财";
private int age=5;
String color = "red";
public Dog(){
}
public Dog(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public void bark(){
System.out.println(name+"汪汪叫");
}
}
public class Test {
public static void main(String[] args) {
Dog dog =new Dog();
System.out.println(dog.getName()+" "+dog.getAge()+" "+dog.getColor());
}
}
上面这个例子中,我在Dog类中就进行了初始化,并且成功打印了出来。
五、访问限定符
Java中有四种访问修饰限定符。它们可以控制成员变量和方法是否可以在类外直接被使用。
这是成员方法和成员变量被这四个访问修饰限定符修饰之后可以被访问的区域。
接下里,我将给一个例子:
class Dog{
private String name="旺财";
public int age=5;
String color = "red";
public Dog(){
}
public Dog(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public void bark(){
System.out.println(name+"汪汪叫");
}
}
public class Test {
public static void main(String[] args) {
Dog dog =new Dog();
//System.out.println(dog.name);private修饰,因此在别的类中无法访问。
System.out.println(dog.age);//public修饰,可以在外类中访问。
System.out.println(dog.color);//没有修饰符
}
}
注意:1.default指什么都不写时的默认访问权限。
2.protected主要用于继承。
六、static成员
在Java中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对
象,是所有对象所共享的
6.1 static修饰成员变量
static修饰的成员变量,被称为类成员/静态成员变量。他们是被所以对象所共享的。
下面我将给一个例子:
class Student {
public String name;
public int age;
public static String classRoom = "Bit106";
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Test {
public static void main(String[] args) {
Student s1 = new Student("wang",18);
Student s2 = new Student("zhu",17);
Student s3 = new Student("zhang",19);
System.out.println(s1.name+" "+s1.classRoom);
System.out.println(s2.name+" "+s2.classRoom);
System.out.println(s3.name+" "+s3.classRoom);
}
}
我们看见,当我们用static定义班级的时候,无论哪个对象调用,他最终都是同一个值。
6.2 修饰成员方法
在java中,如果用private修饰成员变量,public修饰成员方法之后,classRoom应该使用被static修饰的成员方法进行访问。
例子如下:
class Student {
private String name;
private int age;
private static String classRoom = "Bit106";
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public static String getClassRoom(){
return classRoom;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static void setClassRoom(String classRoom) {
Student.classRoom = classRoom;
}
}
public class Test {
public static void main(String[] args) {
Student s1 = new Student("wang",18);
Student s2 = new Student("zhu",17);
Student s3 = new Student("zhang",19);
System.out.println(s1.getName()+" "+Student.getClassRoom());
System.out.println(s2.getName()+" "+Student.getClassRoom());
System.out.println(s3.getName()+" "+Student.getClassRoom());
}
}
我们看到,我的所有成员变量都是private修饰,且classRoom是private static修饰。成员变量可以通过get方法访问,set方法修改。而classRoom可以用static修饰的方法访问。注意是使用类名进行访问。
注意:1.用static修饰的方法不属于某个对象,而是类方法。
2.访问静态方法的时候最好使用类名进行访问。
3.不能在静态方法中访问任何非静态变量。
4.在静态方法中无法访问非静态方法。因为非静态方法有this引用,在静态方法中无法进 行this引用。
5.静态方法无法重写。不能实现多态。
七、代码块
使用{}定义的的一段代码称为代码块。有普通代码块,构造代码块,静态代码块,同步代码块。
7.1 普通代码块
普通代码块就是定义在方法中的代码块,例子如下:
public static void main(String[] args) {
{
int a=10;
System.out.println(a);
}
int a=20;
System.out.println(a);
}
例子中先定义了一个a,并且输出了它。代码块结束后,必须重新定义一个a,因为上面一个a的生命周期就是在那个代码块之中。
7.2 构造代码块
构造代码块也叫实例代码块,它是定义在类中的代码块。一般可以用来初始化成员变量。
例子如下:
class Dog {
private int age;
private String name;
//实例代码块
{
this.age = 5;
this.name = "旺财";
}
public void show() {
System.out.println(name + " " + age);
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.show();
}
}
7.3 静态代码块
静态代码块是用static定义的代码块,一般用来初始化静态成员。例子如下:
class Dog{
private static int age;
private static String name;
static{
name="旺财";
age=10;
}
public static int getAge() {
return age;
}
public static String getName() {
return name;
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
System.out.println(dog.getAge()+" "+dog.getName());
}
}
7.4 代码块运行次序
例子如下:
class Dog{
public int age;
public String name;
public void func(){
System.out.println("普通代码块");
}
{
System.out.println("实例代码块");
}
static{
System.out.println("静态代码块");
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.func();
}
}
上面例子说明,静态代码块是最先运行的。普通代码块是最后运行的。
注意:1.静态代码块之后执行一次。
2.实例代码块只有创建对象的时候才会执行。
八、内部类
如果一个类定义在另一个类或者方法的内部,那么就称前者是内部类,后者为外部类。例子如下:
class B{
class A{
}
}
8.1 内部类的分类
内部类有一下几种:
class A{
//实例内部类
class B{
}
//静态内部类
static class C{
}
public void test() {
//局部内部类
class D{
}
}
}
8.2 实例内部类
例子如下:
class A{
private int a;
static int b;
int c;
public void method1(){
System.out.println(a);
}
public void method2(){
System.out.println(b);
}
class B{
public void put(){
a=1000;
b=2000;
method1();
method2();
c=1500;
System.out.println(c);
}
}
}
public class Test {
public static void main(String[] args) {
A a = new A();
A.B ab = a.new B();
ab.put();
}
}
注意:1.外部类的所有成员变量在内部类方法中都可以访问。
2.实例内部类也受private,public等访问修饰限定符的约束。
3.要创建内部类的对象:
OutClass.InnerClass innerClass1 = new OutClass().new InnerClass();
4.外部类不能直接访问内部类对象,访问前应该创建内部类对象。
8.3静态内部类
例子如下:
class A{
private int a;
static int b;
int c;
public void method1(){
System.out.println(a);
}
public static void method2(){
System.out.println(b);
}
static class B{
public void put(){
//a=1000;//a不是类成员变量,编译失败。
b=2000;
//method1();//method1不是类成员方法,编译失败。
method2();
//c=1500; //c不是类成员变量,编译失败。
//System.out.println(c);
}
}
}
public class Test {
public static void main(String[] args) {
A.B ab = new A.B();
ab.put();
}
}
注意:1. 在静态内部类中只能访问外部类中的静态成员 ,如果想访问,就先创建外部类对象进行访问。
2. 创建静态内部类对象时,不需要先创建外部类对象。