我们知道,在之前的Date这个类中,我们需要调用setDate这个方法来初始化。其实我们还有好几种方法,我们先给大家介绍一下构造方法
举个栗子:
public Date() {
}
这就是一个最简单的不带参数的构造方法。在创建对象的时候,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
当我们实例化一个对象的时候,必须有以下这两部,但不是一定只有这两步
为对象分配内存
调用合适的构造方法?
这句话其实另有玄机,代表构造方法不一定只有一个
public class Date {
public int year;
public int month;
public int day;
//不带参数的构造方法
public Date() {
System.out.println("调用不带参数的构造方法");
}
//带三个参数的构造方法
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
System.out.println("调用带三个参数的构造方法");
}
//打印日期
public void printDate() {
System.out.println(year + "年" + month + "月" + day + "日");
}
public static void main(String[] args) {
//调用不带参数的构造方法
Date date1 = new Date();
//调用带三个参数的构造方法
Date date2 = new Date(2022,05,24);
}
}


那么我们要注意:当程序没有构造方法的时候,编译器会默认帮我们生成一个不带参数的构造方法。如果你自己写了构造方法,那么编译器就不会再自动生成一个不带参数的构造方法了,我们可以通过下面的代码进行检验
public class Date {
public int year;
public int month;
public int day;
//带三个参数的构造方法
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
System.out.println("调用带三个参数的构造方法");
}
//打印日期
public void printDate() {
System.out.println(year + "年" + month + "月" + day + "日");
}
public static void main(String[] args) {
//调用不带参数的构造方法
Date date1 = new Date();
}
}

我们可以看见,这段代码中,我们自己写了一个带三个参数的构造函数,然后main方法中却调用了不带参数的构造函数,通过图片我们得知,这报错了,是因为我们自己生成构造函数的话,编译器就不会再帮我们生成不带参数的构造函数,所以在主函数调用不带参数的构造函数会报错
名字必须与类名相同

没有返回值类型,设置为void也不行

创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
重载:方法名相同,参数裂变不同,和返回值没有关系
如果用户没有自己定义构造函数,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的。(所以一个类是一定至少含有一个构造函数)
编译器帮我们实现的构造函数:右键->generate->constructer->选中要操作的属性
编译器帮我们实现show函数:右键->generate->toString()
构造方法中,可以通过this调用其他构造方法来简化代码
class Student {
public String name;
public int age;
public double score;
public String sex;
//不带参数的构造函数
public Student() {
this("剪秋",22,98,"女");//调用Student类中带4个参数的构造函数
}
//带三个参数的构造函数
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
//带四个参数的构造函数
public Student(String name, int age, double score, String sex) {
this.name = name;
this.age = age;
this.score = score;
this.sex = sex;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
", sex='" + sex + '\'' +
'}';
}
}
public class StudentDemo {
public static void main(String[] args) {
Student student1 = new Student();
System.out.println(student1);
}
}

注意:
this必须放在构造函数的第一行
public Student() {
System.out.println("this只能放在第一行");
this("剪秋",22,98,"女");//调用Student类中带4个参数的构造函数
}

一个构造函数里面只能有一个this
public Student() {
this("剪秋",22,98,"女");//调用Student类中带4个参数的构造函数
this("宝娟",25,77);
}

不能成环
//不带参数的构造函数
public Student() {
this("剪秋",22,98);//调用Student类中带4个参数的构造函数
}
//带三个参数的构造函数
public Student(String name, int age, double score) {
this();
this.name = name;
this.age = age;
this.score = score;
}

我们之前写过的代码就是默认初始化的
public class Date {
//默认初始化:初始化为对应的null
public int year;
public int month;
public int day;
public static void main(String[] args) {
}
}
public class Date {
//就地初始化:不太好
public int year = 2022;
public int month = 05;
public int day = 24;
public static void main(String[] args) {
}
}
代码编译完成后,编译器会将所有就地初始化的语句添加到各个构造函数中

就目前为止,我们针对目前所学习的知识,来创建一个猫的类吧
class Cat {
public String name;
public int age;
public String color;
public Cat() {
//可以在这里面进行初始化
this.name = "哈哈";
this.age = 3;
this.color = "黑色";
System.out.println("带一个参数的构造方法");
}
public Cat(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
System.out.println("带三个参数的构造方法");
}
public void sleep() {
System.out.println(this.name + "正在睡觉");
}
public void eat() {
System.out.println(this.name + "正在吃饭");
}
}
public class CatDemo {
public static void main(String[] args) {
Cat cat1 = new Cat("啦啦",4,"白色");
cat1.sleep();
cat1.eat();
Cat cat2 = new Cat();
cat2.sleep();
cat2.eat();
}
}

面向对象程序三大特性:封装、继承、多态。而类和对象阶段,主要研究的就是封装特性。封装呢,简单来说,就是套壳屏蔽细节。
比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器,USB插孔等,让用户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU、显卡、内存等一些硬件元件。
对于计算机使用者而言,不用关心内部核心部件,比如主板上线路是如何布局的,CPU内部是如何设计的等,用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互(公开的方法 和 私有的属性之间结合)
封装还可以降低代码的耦合度(意思就是关联程度,比如:name改成myname影响不会特别大)
我们刚刚完成了一个猫类,现在,我们给他改成封装的思考方式
class Cat {
//1.我们先把访问修饰限定符改成private
//这些被private修饰的 属性 或者 方法,只能在当前Cat当中使用->安全,类外不课件
//对类的实现细节 进行隐藏
private String name;
private int age;
private String color;
//2.我们可以生成一些get set 方法
//右键->Generate->getter and setter
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 Cat() {
//可以在这里面进行初始化
this.name = "哈哈";
this.age = 3;
this.color = "黑色";
System.out.println("带一个参数的构造方法");
}
public Cat(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
System.out.println("带三个参数的构造方法");
}
//之前自己定义的方法
public void sleep() {
System.out.println(this.name + "正在睡觉");
}
public void eat() {
System.out.println(this.name + "正在吃饭");
}
//生成一个show方法
//右键->Generate->toString()
//打印:System.out.println(cat);
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
'}';
}
}
public class CatDemo {
public static void main(String[] args) {
Cat cat = new Cat();
cat.setName("嘻嘻");//又可以通过刚刚生成的setter方法把名字传过去
String name = cat.getName();//可以通过getter方法获取到名字
System.out.println(name);
System.out.println("--------------");
//name age color是私有属性,类外访问不到
//cat.name = "嘻嘻";
//cat.age = 10;
//cat.color = "⻩⾊";
System.out.println(cat);
}
}
我们可以看到,类里面的属性被设置成了私有,但是我们还生成了一系列getter,setter方法来给类的使用者去获取到相关信息,所以这就是将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
那么现在,在主函数我们想要直接访问name,age,color方法是访问不到的,只能通过getter,setter方法


我们接下来继续看,如果我们传入的对象是空的时候,是什么效果?
public static void main(String[] args) {
Cat cat = null;
System.out.println(cat);//传过去null,打印的就是字符串null
}
我们看运行结果,是null


我们在输入数据的时候,同样可以采用构造方法
public static void main(String[] args) {
Cat cat1 = new Cat("华妃",4,"橘⻩⾊");
cat1.show();
cat1.sleep();
Cat cat2 = new Cat("欣贵人",14,"红色");
cat2.show();
cat2.sleep();
Cat cat3 = new Cat();
cat3.sleep();
cat3.show();
}

但是奇怪的是,cat3我们并没有初始化啊,为什么它叫哈哈了?
实际上,我们看上面的带一个参数的构造函数
public Cat() { //可以在这里面进行初始化 this.name = "哈哈"; this.age = 3; this.color = "黑色"; System.out.println("带一个参数的构造方法"); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
我们在这里面也进行过初始化,如果我们之后有传入其他的数据,那么就使用我们传过来的数据,要不就使用这里面构造的数据
为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间。把多个类收集在一起成为一组,称为软件包,有点类似于目录。
包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一个包中的类不想被其他包中的类使用。包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。
Java 中已经提供了很多现成的类供我们使用. 例如Date类:可以使用 java.util.Date 导入java.util这个包中的 Date类.
public class TimeStamp {
public static void main(String[] args) {
java.util.Date date = new java.util.Date();
//得到一个毫秒级别的时间戳
System.out.println(date.getTime());
}
}
我们可以通过import语句简化写法
import java.util.Date;
public class TimeStamp {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date.getTime());
}
}
如果需要使用 java.util 中的其他类, 可以使用 import java.util.*
import java.util.*;//导⼊util的包,但是只会访问需要的那个功能
public class TimeStamp {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date.getTime());//时间戳需要用到util下面的功能
System.out.println("---------------");
int[] array = {1,3,5,7,9};
System.out.println(Arrays.toString(array));//toString也需要用到util下面的功能
}
}
但是有可能,Date功能在util包和sql包下面都有,恰好我们都import了,那么就会报错
import java.util.*;
import java.sql.*;
public class TimeStamp {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date.getTime());
}
}

那么我们需要显示指定才能解决,像下面这样
import java.util.*;
import java.sql.*;
public class TimeStamp {
public static void main(String[] args) {
java.util.Date date = new java.util.Date();
System.out.println(date.getTime());
}
}
我们还可以可以使用import static导入包中静态的方法和字段。(不推荐)
import static java.lang.Math.*;
public class TimeStamp {
public static void main(String[] args) {
double x = 30;
double y = 40;
// 静态导入的方式写起来更方便一些.
// double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
double result = sqrt(pow(x, 2) + pow(y, 2));
System.out.println(result);
}
}
注意事项: import 和 C++ 的 #include 差别很大。C++ 必须 #include 来引入其他文件内容,,但是 Java 不需要,import 只是为了写代码的时候更方便。import 更类似于 C++ 的 namespace 和 using
⼀般全部小写,公司域名逆序
基本规则
在文件的最上方加上一个 package 语句指定该代码在哪个包中.
包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.baidu.demo )
包名要和代码路径相匹配. 例如创建 com.baidu.demo 的包, 那么会存在一个对应的路径 com/baidu/demo 来存储
代码.
如果一个类没有 package 语句, 则该类被放到一个默认包中
创建方法
src->右键->New->Package

公司域名逆序,全部小写,中间用.分隔

这时候我们就可以看见文件夹创建了


public:公共的,公开的,哪里都能访问
default:什么都不写,只能在同一个包里面访问
private:只能在当前类访问
具体的访问修饰限定符我们下一篇博客会详细讲解
Computer类位于pack.test.demo包中,TestComputer位置pack.test.demo2包中:
Computer:
package pack.test.demo;
public class Computer {
private String cpu;//cpu
private String memory;//内存
public String screen;//屏幕
String brand;//品牌
public Computer(String cpu, String memory, String screen, String brand) {
this.cpu = cpu;
this.memory = memory;
this.screen = screen;
this.brand = brand;
}
public void PowerOn() {
System.out.println("开机");
}
public void PowerOff() {
System.out.println("关机");
}
public void SurfInternet() {
System.out.println("上网");
}
}
TestDemo:
package pack.test.demo2;
import pack.test.demo.Computer;//引用了pack.test.demo里面的Computer这个类
public class TestComputer {
public static void main(String[] args) {
Computer computer = new Computer("CPU","MEMORY","SCREEN","BRAND");
System.out.println(computer.screen);//public 到处可以访问
//System.out.println(computer.cpu);//private 只能在当前类访问
//System.out.println(computer.brand);//默认权限 只能在同一个包下访问
}
}

java.lang:系统常用基础类(String,object)java.lang.reflect:Java反射基础包java.net:网络编程开发包java.sql:数据库开发支持包java.util:工具程序包(集合类等),非常重要java.io:I/O编程开发包我们之前创建的Student类,里面有以下这四个属性
public String name;
public int age;
public double score;
public String sex;
那么我们知道,每个人的姓名、年龄、分数和性别可能都是不同的,那么如果这几个同学都是一个班级的,那该怎么表示?
我们仍然可以创建一个成员变量,然后分别赋值。我们也可以创建一个static修饰的成员变量,被static修饰的成员变量,称之为静态成员(类成员),他不属于某个具体的对象,使所有对象所共享的
static修饰的成员变量,称为静态成员变量。
它最大的特性就是:不属于某个具体的对象,是所有对象所共享的。
那么他的特性都有:
不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问,而且这样也不需要new对象了
Student.class;//推荐
student.class;//不推荐
JDK7及以前,HotSpot(Java虚拟机)中存储在方法区,JDK8及之后,类变量存储在Java堆中
其实方法区和堆逻辑上都属于同一个等级的关系,只不过在
JVM当中实现这个东西的时候,把他放在了堆里
类变量存储在方法区当中
生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)
类在的话就在,不在就没了
举个栗子吧:
class Student {
//成员变量(字段/属性)
public String name;
public int age;
public double score;
public String sex;
public static String classRoom = "0301";//静态的成员变量
public Student(String name, int age, double score, String sex) {
this.name = name;
this.age = age;
this.score = score;
this.sex = sex;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
", sex='" + sex + '\'' +
", class='" + classRoom +'\'' +
'}';
}
}
public class StudentDemo {
public static void main(String[] args) {
Student student1 = new Student("甄嬛",20,98,"女");
Student student2 = new Student("沈眉庄",21,97,"女");
Student student3 = new Student("安陵容",22,99,"女");
System.out.println(Student.classRoom);//推荐:类名.静态成员变量
System.out.println("---------------");
//也可以通过对象.静态成员变量访问
System.out.println(student1.classRoom);
System.out.println(student2.classRoom);
System.out.println(student3.classRoom);
}
}

那么我们可以调试一下,看看静态的成员变量是否存在于某个具体的变量当中

正常情况下,一个类当中成员变量是要设置成private ,成员方法是要设置成public的,但是private修饰之后,在类外是访问不到的。那么假如要是把静态成员变量设置成private修饰的,在类外怎么访问呢?
class Student2 {
//成员变量(字段/属性)
public String name;
public int age;
public double score;
public String sex;
private static String classRoom = "0301";//静态的成员变量,被private修饰了
}
public class StudentDemo2 {
public static void main(String[] args) {
System.out.println(Student.classRoom);
}
}

我们可以通过静态的成员方法,来实现在类外访问被private修饰的静态成员变量
class Student2 {
//成员变量(字段/属性)
public String name;
public int age;
public double score;
public String sex;
private static String classRoom = "0301";//静态的成员变量,被private修饰了
public static String getClassRoom() {
return classRoom;
}
}
public class StudentDemo2 {
public static void main(String[] args) {
System.out.println(Student2.getClassRoom());
}
}
静态方法的特性:
不属于某个具体的对象,是类方法
可以通过对象调用,也可以通过类名.静态方法名(…)方式调用,更推荐使用后者
Student.getClassRoom();
student.getClassRoom();
静态方法没有隐藏的this引用参数,因此不能在静态方法中访问任何非静态成员变量
class Student2 {
//成员变量(字段/属性)
public String name;
public int age;
public double score;
public String sex;
private static String classRoom = "0301";//静态的成员变量,被private修饰了
public Student2(String name, int age, double score, String sex) {
this.name = name;
this.age = age;
this.score = score;
this.sex = sex;
}
public static String getClassRoom() {
this("齐妃",30,88,"女");//静态成员方法里面是不能调用this方法的
age = age + 1;//静态成员方法里面是不能引用非静态变量的
System.out.println(classRoom);//静态成员方法里面可以引用静态成员变量
return classRoom;
}
}
public class StudentDemo2 {
public static void main(String[] args) {
System.out.println(Student2.getClassRoom());
}
}

静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用
class Student2 {
//成员变量(字段/属性)
public String name;
public int age;
public double score;
public String sex;
private static String classRoom = "0301";//静态的成员变量,被private修饰了
public static String getClassRoom() {
//doClass();//静态成员方法当中不能调用普通方法
return classRoom;
}
public void doClass() {
System.out.println(this.name + "正在上课");
}
}
public class StudentDemo2 {
public static void main(String[] args) {
System.out.println(Student2.getClassRoom());
}
}

通过对象.成员变量可能会产生问题
public static void main(String[] args) {
Student student = null;//student不指向任何对象
student.classRoom = "0302";//student不指向任何对象,所以student.classRoom不知道指向的是哪里,就被赋值成0302了
System.out.println(student.classRoom);
}
我们要初始化静态的成员变量的时候,一般不会使用构造函数,构造方法中初始化的是与对象相关的实例属性
静态成员变量的初始化分为两种:就地初始化和静态代码块初始化。
就地初始化就是刚才那几个例子
private static String classRoom = "0301";
静态代码块初始化,在学习他之前,还得学学代码块
实例代码块是优先于构造方法执行的。实际上从字节码的角度来看,是把实例代码块当中的内容,拷贝到了构造方法之前。一般用来初始化普通的成员变量
当有对象创建时,才会执行实例代码块,实例代码块执行完成后,最后构造方法执行
class Student {
public String name;
private int age;
private double score;
public static String classes;
//构造方法
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
System.out.println("构造方法:带三个参数");
}
//实例代码块
{
this.name = "瑛贵人";
this.age = 22;
this.score = 88.8;
System.out.println("实例代码块:比构造方法要先执行,一般用来初始化普通的成员变量");
}
}
public class TestDemo {
public static void main(String[] args) {
Student student1 = new Student("华妃",18,99.9);
}
}

先执行静态代码块,再执行实例代码块。静态代码块只会执行一次。如果写了多个静态代码块,会根据书写的先后顺序来进行赋值(其实就是相当于之前的被复制了)
class Student {
public String name;
private int age;
private double score;
public static String classes;
//构造方法
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
System.out.println("构造方法:带三个参数");
}
//实例代码块
{
this.name = "瑛贵人";
this.age = 22;
this.score = 88.8;
System.out.println("实例代码块:比构造方法要先执行,一般用来初始化普通的成员变量");
}
//静态代码块
static {
classes = "0301";
System.out.println("静态代码块:最先执行,一般用来初始化静态成员变量");
}
}
public class TestDemo {
public static void main(String[] args) {
Student student1 = new Student("华妃",18,99.9);
}
}

静态代码块的注意事项:
静态代码块也是不依赖对象的,里面不能出现非静态成员
//静态代码块
static {
this("富察贵人",78,11);//静态代码块里面不能出现this
age = age + 1;//静态代码块里面不能出现非静态成员变量
classes = "0301";
System.out.println("静态代码块:最先执行,一般用来初始化静态成员变量");
}

出现两个静态代码块的时候,打印的结果是最后一个static的值(之前的被覆盖了)
class Student {
public String name;
private int age;
private double score;
public static String classes;
//构造方法
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
System.out.println("构造方法:带三个参数");
}
//实例代码块
{
this.name = "瑛贵人";
this.age = 22;
this.score = 88.8;
System.out.println("实例代码块:比构造方法要先执行,一般用来初始化普通的成员变量");
}
//静态代码块
static {
classes = "0301";
}
static {
classes = "0302";
}
}
public class TestDemo {
public static void main(String[] args) {
System.out.println(Student.classes);
}
}

在普通的成员方法里面是可以使用静态的成员变量的
class Student {
public String name;
private int age;
private double score;
public static String classes;
//构造方法
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
System.out.println("构造方法:带三个参数");
}
public void doClass() {
//在普通的成员方法里面是可以使用静态局部变量的
System.out.println(classes);
}
}
public class TestDemo {
public static void main(String[] args) {
Student student1 = new Student("华妃",18,99.9);
student1.doClass();
}
}

静态的成员方法中,不能访问非静态的成员
public static void func() {
//在静态成员函数里面不能访问非静态成员
doclass();
System.out.println(age);
//在静态成员函数里面访问静态局部变量可以
System.out.println(classes);
}

静态代码块先执行,并且只执行一次,在类加载阶段执行
class Person {
public String name;
public int age;
public Person(String name,int age) {
this.name = name;
this.age = age;
System.out.println("构造方法");
}
{
System.out.println("实例代码块");
}
static {
System.out.println("静态代码块");
}
}
public class TestDemo2 {
public static void main(String[] args) {
Person person1 = new Person("瑛贵人",20);
System.out.println("----------------------");
Person person2 = new Person("浣碧",22);
}
}

实例代码块只有在创建对象的时候执行
class Student {
public String name;
private int age;
private double score;
public static String classes;
//构造方法
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
System.out.println("构造方法:带三个参数");
}
//实例代码块
{
this.name = "瑛贵人";
this.age = 22;
this.score = 88.8;
System.out.println("实例代码块:比构造方法要先执行,一般用来初始化普通的成员变量");
}
//静态代码块
static {
classes = "0301";
}
static {
classes = "0302";
System.out.println("打印静态代码块");
}
}
public class TestDemo {
public static void main(String[] args) {
System.out.println(Student.classes);
}
}

当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。在 Java 中,可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。内部类也是封装的一种体现。
用法:
class OuterClass {
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
class InnerClass {
//这里就是实例内部类
}
}
如何实例化内部类对象:
1.外部类名.内部类名 变量 = new 外部类名().new 内部类名();
2.外部类名 变量1 = new 外部类名();
外部类名.内部类名 变量2 = 变量1.new 内部类名();
举例:
方式一:
OuterClass.InnerClass innerclass1 = new OuterClass().new InnerClass();
方式二:
OuterClass outerclass = new OuterClass();
OuterClass.InnerClass innerclass2 = outerclass.new InnerClass();
实例内部类当中不能定义静态的成员变量的。(非得要定义,可以这样:定义一个final属性的值,这样的话编译期间就确定值了,public static final int data = 10;)
class OuterClass {
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
class InnerClass {
//这里就是实例内部类
public static int data4 = 40;//必须要加final才不报错
public static final int data5 = 50;
}
}

如果实力内部类当中,创建的变量跟外部类当中的变量重名了,优先使用自己的
class OuterClass {
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
class InnerClass {
//这里就是实例内部类
public int data1 = 40;
private int data2 = 50;
public void display() {
System.out.println("data1 = " + data1);
System.out.println("data2 = " + data2);
}
}
}
public class TestDemo1 {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.display();
}
}

那么我们如果想要获取到外部类的成员变量呢?
外部类类名.外部类成员变量
class OuterClass {
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
class InnerClass {
//这里就是实例内部类
public int data1 = 40;
private int data2 = 50;
public void display() {
System.out.println("内部类当中的data1 = " + this.data1);
System.out.println("内部类当中的data2 = " + this.data2);
System.out.println("外部类当中的data1 = " + OuterClass.this.data1);
System.out.println("外部类当中的data2 = " + OuterClass.this.data2);
}
}
}
public class TestDemo1 {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.display();
}
}

注意:我们还使用了this,我们可以注意到:实力内部类当中,不仅有自己的this,也有外部类的this
不能包含静态的方法
class OuterClass {
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
class InnerClass {
//这里就是实例内部类
public int data1 = 40;
private int data2 = 50;
public static void func() {
System.out.println("实例内部类里面不能出现静态方法");
}
public void display() {
System.out.println("内部类当中的data1 = " + this.data1);
System.out.println("内部类当中的data2 = " + this.data2);
System.out.println("外部类当中的data1 = " + OuterClass.this.data1);
System.out.println("外部类当中的data2 = " + OuterClass.this.data2);
}
}
}
public class TestDemo1 {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.display();
}
}

在实力内部类里面的普通的成员方法里面,不能定义static final属性的值
public void display() {
static final int c = 90;
}

匿名对象:一般使用在只用一次的时候,但是每访问一次都要重新new一下
public static void main(String[] args) {
//匿名对象:new OuterClass()
System.out.println(new OuterClass().data1);
System.out.println(new OuterClass().data1);//每访问一次就需要重新new一下
}
代码汇总:
class OuterClass {
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
class InnerClass {
//这里就是实例内部类
public int data1 = 40;
private int data2 = 50;
public static final int data4 = 60;
/*public static void func() {
System.out.println("实例内部类里面不能出现静态方法");
}*/
public void display() {
//static final int c = 90;
System.out.println("内部类当中的data1 = " + this.data1);
System.out.println("内部类当中的data2 = " + this.data2);
System.out.println("--------------------------");
System.out.println("外部类当中的data1 = " + OuterClass.this.data1);
System.out.println("外部类当中的data2 = " + OuterClass.this.data2);
System.out.println("--------------------------");
System.out.println("外部类当中的data3 = " + OuterClass.this.data3);
System.out.println("内部类当中的data4 = " + this.data4);
}
}
}
public class TestDemo1 {
public static void main2(String[] args) {
//匿名对象:new OuterClass()
System.out.println(new OuterClass().data1);
System.out.println(new OuterClass().data1);//每访问一次就需要重新new一下
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.display();
}
}
用法:
class OuterClass2 {
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
static class InnerClass2 {
}
}
如何实例化静态内部类
外部类.内部类 变量 = new 外部类.内部类();
举例:
class OuterClass2 {
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
static class InnerClass2 {
}
}
public class TestDemo2 {
public static void main(String[] args) {
OuterClass2.InnerClass2 innerClass2 = new OuterClass2.InnerClass2();
}
}
在静态内部类当中,只能访问外部类当中静态成员变量
要想访问外部类非静态成员变量,就要提供外部类对象(即
new一个外部类对象)
class OuterClass2 {
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
static class InnerClass2 {
public int data4 = 40;
private int data5 = 50;
public static int data6 = 60;
public void show() {
//这样是访问不了的
System.out.println(data1);
System.out.println(data2);
}
}
}

我们需要先new一个外部类对象,在通过外部类对象去调用
class OuterClass2 {
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
static class InnerClass2 {
public int data4 = 40;
private int data5 = 50;
public static int data6 = 60;
OuterClass2 outer = new OuterClass2();//new一个外部类对象
public void show() {
System.out.println(outer.data1);//外部类对象.成员变量
System.out.println(outer.data2);//外部类对象.成员变量
System.out.println(data3);//外部类当中data3是静态的,可以直接访问
System.out.println(data4);
System.out.println(data5);
System.out.println(data6);
}
}
}
public class TestDemo2 {
public static void main(String[] args) {
OuterClass2.InnerClass2 innerClass2 = new OuterClass2.InnerClass2();
innerClass2.show();
}
}

写法:
class Test {
}
public class TestDemo3 {
public static void main(String[] args) {
new Test() {
}.test();
}
}
代码:
class Test {
public int a = 19;
public void test() {
System.out.println("test()");
}
}
public class TestDemo3 {
public static void main(String[] args) {
new Test() {
public int c = 10;//1.匿名内部类可以创建变量
public void test01() {//2.匿名内部类可以写方法
System.out.println("test01()");
}
@Override//匿名内部类还可以对被匿名的类里面的方法进行重写
public void test() {
System.out.println("对test函数进行重写");
}
}.test();
}
}