面向对象的基本概念
类和对象
1.类的声明
[修饰符关键字] class 类名 [extends 父类名] [implements 接口1,接口2]{
//类的主体内容
}
public class tt extends Test implements TestInter {
}
2.类的变量成员
变量成员的声明格式
[修饰关键字] 类型 变量名;
public class TT{
public String name;
private int age;
}
3.类的方法成员
声明格式
[修饰关键字] 返回类型 方法名称( [参数类型和参数列表] ) {
}
类的方法成员可以和类同名
public class TT{
//返回字符串类型的方法成员
public String method1(){
String name = "name";
return name;
}
//没有返回值的方法成员
public void method2(){
System.out.println("这是一个没有返回值的方法成员");
}
}
4.类的构造方法
public class Test {
// 构造方法
public Test(){
System.out.println("这是一个无参的构造函数");
}
public Test(String n){
System.out.println("带参的构造函数参数是:"+n);
}
public static void main(String[] args) {
Test t = new Test();
Test tt = new Test("李四");
}
}
如果不需要构造方法 可以不写 编译器会在编译的时候自动给你加上一个无参的构造函数
如果自己定义了一个带参的构造方法 编译器将不再自动添加无参的构造方法 如果需要无参的构造方法需要手动添加构造方法的
5.方法重载
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。最常用的地方就是构造器的重载。方法能够在同一个类中。无法以返回值类型作为重载函数的区分标准
上面的一个带参数的构造方法和没有参数的构造方法就是重载
6.对象
public class Test {
// 构造方法
Test(){
System.out.println("这是一个无参的构造函数");
}
public Test(String n){
System.out.println("带参的构造函数参数是:"+n);
}
public static void main(String[] args) {
Test t ; //声明对象
t= new Test(); //创建对象
}
}
类和成员修饰符
修饰符 | 可修饰对象 | 含义 |
---|---|---|
public(访问修饰符) | 类、接口、成员变量、成员方法 | 任何地方都可以访问,对访问无限制。 |
protected(访问修饰符) | 成员变量、成员方法、内部类 | 同一个包内或者不同包内的子类可以访问。 |
private(访问修饰符) | 成员变量、成员方法、内部类 | 同一个类内可以访问。 |
默认(default)(访问修饰符) | 同一个包内可以访问。 | |
static(非访问修饰符) | 成员变量、成员方法、内部类 | 静态变量:static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为 static 变量。 静态方法:static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。 静态内部类:静态内部类不能够直接对外调用,独立于该类的任何实例对象。 静态变量和静态方法的使用:类名.方法名 或 类名.变量名 只能用于类中的变量和方法 |
final(非访问修饰符) | 类、成员变量、成员方法 | final 变量:变量一旦赋值后,不能被重新赋值。被 final 修饰的实例变量必须显式指定初始值。 final 修饰符通常和 static 修饰符一起使用来创建类常量。 final 方法:类中的 final 方法可以被子类继承,但是不能被子类修改重写。 声明 final 方法的主要目的是防止该方法的内容被修改。 final 类:final 类不能被继承。 |
abstract(非访问修饰符) | 类、成员方法 | 抽象类:抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。 一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误。接口是一个完全的抽象类 抽象方法:抽象方法是一种没有任何实现的方法,该方法的的具体实现由子类提供。 抽象方法不能被声明成 final 和 static。 任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。 如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。 |
synchronized(非访问修饰符) | 成员方法 | synchronized 关键字声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符。 |
transient(非访问修饰符) | 成员变量 | 序列化的对象包含被 transient 修饰的实例变量时,java 虚拟机(JVM)跳过该特定的变量。 该修饰符包含在定义变量的语句中,用来预处理类和变量的数据类型。参考 |
volatile(非访问修饰符) | 成员变量 | volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。 |
public class Test {
public static Object a;
static class aa{
aa(){
System.out.println("aa");
}
public void method1(){
System.out.println("静态内部类");
}
}
public static void main(String[] args) {
Test.a = new Test.aa();
((aa) Test.a).method1();
}
}
this关键字
当前对象的引用
public class Test {
String name;
Test(String name){
name = name;
System.out.println("不使用this赋值的参数name="+name+",类属性name="+this.name);
this.name = name;
System.out.println("使用this赋值的参数name="+name+",类属性name="+this.name);
}
public static void main(String[] args) {
Test t = new Test("张三");
}
}
public class Test {
int i = 0;
Test method(){
i++;
return this;
}
void getI(){
System.out.println(i);
}
public static void main(String[] args) {
Test t = new Test();
t.method().method().method().getI();
}
}
public class Test {
int i = 10;
void method1(){
Test1.method(this);
}
public static void main(String[] args) {
Test t = new Test();
t.method1();
}
}
class Test1{
static Test method(Test test){
System.out.println("进行逻辑处理,i = "+test.i);
return test;
}
}
在构造器中调用构造器
调用语句必须放在第一条;
public class Test {
Test(String s){
this(1);
System.out.println("这是字符串参数的构造函数s="+s);
}
Test(){
this("字符串");
System.out.println("这是无参构造函数");
}
Test(int i){
System.out.println("i="+i);
}
public static void main(String[] args) {
Test t = new Test();
}
}
成员的初始化
类成员初始化
在方法中未初始化的值是不能使用的在编译时期会报错
而在类的成员变量中未初始化的值则不会报错
这是在类里面的成员变量 会按照数据类型的不同默认赋一个初始值
注意:如果成员变量是非基本数据类型,默认初始值未null ,不能调用其方法,否则会报空指针异常
Exception in thread "main" java.lang.NullPointerException
public class Test {
public static void main(String[] args) {
Test t = new Test();
t.method();
}
String i;
AA a;
void method(){
System.out.println("i:"+i);
System.out.println("a:"+a);
System.out.println(i.length()); //会报错
}
}
class AA{}
指定初始化
public class Test {
public static void main(String[] args) {
Test t = new Test();
}
int g = method2(g); //自引用会报错
int i = method1();
int b = method2(i); //引用其他值不会报错
int method1(){
return 12;
}
int method2(int a){
return 12+a;
}
}
构造器初始化
初始化顺序
public class Test {
public static void main(String[] args) {
System.out.println("执行main");
House house = new House();
house.method();
House.stMethod();
}
static House house2 = new House();
House house3 = new House();
}
class Window {
Window(int i) {
System.out.println("Window(" + i + ")");
}
}
class House {
Window w1 = new Window(1);
House() {
System.out.println("House()");
w3 = new Window(33);
}
static Window w4 = new Window(4);
Window w2 = new Window(2);
static void stMethod() {
System.out.println("stMethod()");
}
void method() {
System.out.println("method()");
}
Window w3 = new Window(3);
{
System.out.println("代码块");
}
static {
System.out.println("静态代码块");
}
}
初始化循序 1静态成员变量和静态代码块 3main方法 4成员变量 5非静态代码块 67构造函数体中成 7调用的方法(静态和非静态)
静态成员变量和静态代码块初始化后重新创建对象时不会再次初始化,同一级别那个在前那个初始化。直接访问静态成员也会使静态代码块初始化。