构造方法
没有定义任何构造方法,编译器会默认生成一个不带参数的构造方法。
构造方法中,可以通过this调用其他构造方法来简化代码,但是构造方法中调用构造方法一定要在第一行(即this(…)必须是构造方法中第一条语句)
public class Date {
public int year;
public int month;
public int day;
// 无参构造方法--内部给各个成员赋值初始值,该部分功能与三个参数的构造方法重复
// 此处可以在无参构造方法中通过this调用带有三个参数的构造方法
// 但是this(1900,1,1);必须是构造方法中第一条语句
public Date() {
//System.out.println(year); 注释取消掉,编译会失败
this(1900, 1, 1);
//this.year = 1900;
//this.month = 1;
//this.day = 1;
}
// 带有三个参数的构造方法
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
}
This指针
构造函数用This
万一构造函数的形参也有与类中的成员相同的变量则会造成冲突
public class Data {
private int year;
private int month;
private int day;
public Data(int year, int month, int day) {
this.year = year;//这么写不会造成冲突和可读性
this.month = month;
this.day = day;
}
public void printDate(){
System.out.println(this.year + "/" + this.month + "/" + this.day);
}
}
初始化
java类似于c++一样,默认类型会规定一个初始化值(即便构造函数没初始化),而自定义类型会调用自定义类型的无参构造函数,如果没有则为nul
数据类型 | 默认值 |
---|---|
byte | 0 |
char | ‘\u0000’ |
short | 0 |
int | 0 |
long | 0L |
boolean | false |
float | 0.0f |
double | 0.0 |
reference(引用) | null |
可以在没构造之前就给出初始化(就地初始化)
public class Date {
public int year = 1900;
public int month = 1;
public int day = 1;
public Date() {
}
}
封装
范围关键字
范围 | private | default | protected | public |
---|---|---|---|---|
同一包中的同类 | 可以 | 可以 | 可以 | 可以 |
同一包中不同类 | 可以 | 可以 | 可以 | |
不同包中的子类(别的包中有当前包的父类) | 可以 | 可以 | ||
不同包中的非子类 | 可以 |
public:可以理解为一个人的外貌特征,谁都可以看得到
default: 对于自己家族中(同一个包中父类对子类)不是什么秘密,对于其他人来说就是隐私了
private:只有自己知道,其他人都不知道
封装的包
import java.util.Date; //引入util文件下的单个包
import java.util.*; //引入util文件下的所有包,*为通配符
mport static java.lang.Math.*; //可以使用import static导入包中静态的方法和字段。
//可以自定义包
//在文件的最上方加上一个 package 语句指定该代码在哪个包中.
//包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.yzy.demo1 ).
//比如路径com.yzy.demo1的包 那么会存在一个对应的路径 com/bit/demo1 来存储代码.
//如果一个类没有 package 语句, 则该类被放到一个默认包中.入src
package com.yzy.demo1;//指明了包的位置
public class Date {
public int year = 1900;
public int month = 1;
public int day = 1;
public Date() {
}
}
官方的包
- java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
- java.lang.reflect:java 反射编程包;
- java.net:进行网络编程开发包。
- java.sql:进行数据库开发的支持包。
- java.util:是java提供的工具程序包。(集合类等) 非常重要
- java.io:I/O编程开发包。
成员变量
static修饰成员变量
- 默认就有,不需要初始化对象,每个对象指向的static成员变量为同一个值
- 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
- 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
- 类变量存储在方法区当中
- 生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)
static修饰成员方法
被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过 静态方法来访问的。
- 不属于某个具体的对象,是类方法
- 可以通过对象调用,也可以通过类名.静态方法名(…)方式调用,更推荐使用后者
- 不能在静态方法中访问任何非静态成员变量
static成员变量初始化
静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性
用代码块初始化
用原地初始化
代码块
普通代码块
普通代码块:定义在方法中的代码块.
构造代码块
构造块:定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量。
public class Student {
//实例成员变量
private String name;
private String gender;
private int age;
private double score;
public Student() {
System.out.println("I am Student init()!");
}
//实例代码块
{
this.name = "yzy";
this.age = 12;
this.sex = "man";
System.out.println("I am instance init()!");
}
public void show() {
System.out.println("name: " + name + " age: " + age + " sex: " + sex);
}
}
public class Main {
public static void main(String[] args) {
Student stu = new Student();
stu.show();
}
}
静态代码块
使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。
public class Student {
private String name;
private String gender;
private int age;
private double score;
private static String classRoom;
//实例代码块
{
this.name = "yzy";
this.age = 12;
this.gender = "man";
System.out.println("I am instance init()!");
}
// 静态代码块
static {
classRoom = "class306";
System.out.println("I am static init()!");
}
public Student() {
System.out.println("I am Student init()!");
}
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();
}
}
各类代码块在创建对象时的先后出现顺序
- 静态代码块先执行,并且只执行一次,在类加载阶段执行
- 当有对象创建时,才会执行实例代码块,实例代码块执行完成后,最后构造方法执行
内部类
当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服 务,那么这个内部的完整结构最好使用内部类。在 Java 中,可以将一个类定义在另一个类或者一个方法的内部, 前者称为内部类,后者称为外部类。内部类也是封装的一种体现。(比如二叉树的节点会在二叉树这个类中写好)
public class OutClass {
class InnerClass {
}
}
// OutClass是外部类
// InnerClass是内部类
内部类分类
public class OutClass {
// 成员位置定义:未被static修饰 --->实例内部类
public class InnerClass1 {
}
// 成员位置定义:被static修饰 ---> 静态内部类
static class InnerClass2 {
}
public void method() {
// 方法中也可以定义内部类 ---> 局部内部类:几乎不用
class InnerClass5 {
}
}
}
实例内部类的创建
// 要访问实例内部类中成员,必须要创建实例内部类的对象
// 而普通内部类定义与外部类成员定义位置相同,因此创建实例内部类对象时必须借助外部类
// 创建实例内部类对象
OutClass.InnerClass innerClass1 = new OutClass().new InnerClass();
// 上述语法比较怪异,也可以先将外部类对象先创建出来,然后再创建实例内部类对象
OutClass.InnerClass innerClass2 = outClass.new InnerClass();
innerClass2.methodInner();
1. 外部类中的任何成员都可以在实例内部类方法中直接访问
2. 实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束
3. 在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名
称.this.同名成员 来访问
4. 实例内部类对象必须在先有外部类对象前提下才能创建
5. 实例内部类的非静态方法中包含了一个指向外部类对象的引用
6. 外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。
静态内部类的创建
public class OutClass {
private int a;
static int b;
public void methodA() {
a = 10;
System.out.println(a);
}
public static void methodB() {
System.out.println(b);
}
// 静态内部类:被static修饰的成员内部类
static class InnerClass {
public void methodInner() {
// 在内部类中只能访问外部类的静态成员
// a = 100; // 编译失败,因为a不是类成员变量
b = 200;
// methodA(); // 编译失败,因为methodB()不是类成员方法
methodB();
}
}
public static void main(String[] args) {
// 静态内部类对象创建 & 成员访问
//静态内部类不能访问外部类的非静态东西
//外部类的成员可以包含静态内部类的元素
OutClass.InnerClass innerClass = new OutClass.InnerClass();//直接用类名来创建
innerClass.methodInner();
}
}
只有子类的时候:
- 在静态内部类中只能访问外部类中的静态成员
- 创建静态内部类对象时,不需要先创建外部类对象
子类和父类都存在的时候:
- 父类静态代码块优先于子类静态代码块执行,且是最早执行
- 父类实例代码块和父类构造方法紧接着执行
- 子类的实例代码块和子类构造方法紧接着再执行
- 第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行
局部内部类
基本不用
匿名内部类
抽象类和接口或者一些方法的临时使用
匿名类继承一个父类:
class person{
public void method(){
System.out.println("父类方法");
}
}
public class Anonymous_inner_class {
public static void main(String[] args) {
person p = new person(){
@Override
public void method() {
System.out.println("重写父类方法");
}
};
p.method();
}
}
匿名类实现一个接口:
interface inter{
void method();
}
public class Anonymous_inner_class2 {
public static void main(String[] args) {
//这里new一个inter接口的子类,但是又把子类向上转型了
inter i = new inter() { //这里一定要()是new inter的一个子类,但这个子类没有名字,如果子类要传参要 <参数>()
@Override
public void method() {
System.out.println("匿名内部类。");
}
};
i.method();
}
}
匿名内部类实现排序
Integer []a={1,2,3,4,5};
//这里相当于new 一个类 implements Comparator<Integer>(); 而内容直接写在这个类下面的花括号
Arrays.sort(a,new Comparator<Integer>(){
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});