Java面向对象三个重要特征

Java面向对象

面向对象三个重要特征:

对象 --- 是现实生活中的存在的事物,(万事万物皆对象) 对象是类的实例, 具有明确定义的属性和行为

类 --- 是对象抽象出的类别模板,对象的设计图纸 用来指明对象的特征和行为

是具有相同特征和共同行为的一组对象的集合

类的声明格式:

[访问修饰符] class 类名{

类的主体成员定义 用来定义行为和特征 }

类的两种基本成员: 属性(成员变量) 方法(成员函数)

属性是用来刻画对象的特征 封装 继承 多态

方法是用来体现对象的功能

类声明 :

Java声明类名的标准规范,即每个单词的第一个字母需要大写

类的方法修饰符

//汽车类

public class Car {

//属性 (成员变量)

//[访问修饰符] 数据类型 字段

String name;

double price;

String color; public final abstract

//方法(成员函数)

//[访问修饰符] 返回值类型 方法名([形参列表]){ }

public void run(){

System.out.printf("汽车:%s__ 价格:%.2f¥__颜色:%s%n",name,price,color); System.out.println("这是我行驶的功能哦!!!");

}

}

/*

对象的创建:

new 1--实例化对象

2--分配内存

Car 宝马 -- 声明一个名为宝马的Car类的引用变量 new Car() -- 实例化对象,分配内存 调用构造函数 Car 宝马=new Car();

-- 表示 名为宝马的引用变量指向堆内存中的实例对象

*/

public static void main(String [] args){ //实例化一个具体的Car实例对象

Car 宝马=new Car();

//访问属性

宝马.name="宝马500";

宝马.price=5000000.00D;

宝马.color="blue";

//访问方法

宝马.run();

Car 奔驰; //声明一个空引用对象 即null 奔驰=new Car();

奔驰.name="奔驰560";

奔驰.price=8000000.00D;

奔驰.color="black";

奔驰.run();

/*对象的销毁

Java的垃圾回收器负责销毁对象

显式销毁 对象名=null(一般不需要显式销毁对象)

*/

奔驰=null; //设置奔驰为空引用

System.out.println(.name);//由于奔驰已经没有指向实例,将抛空引用异常

}

属性和方法

public class Book {

//java中属性一般声明为private

//外界要访问通过公有的getter和setter方法

private String bookName; //注意 属性名首字母小写

private int bookId=0;

private String author="无名"; //可以直接初始化

private float price=0.0F;

//getter方法

public String getBookName() {

return bookName;

}

//setter方法

public void setBookName(String bookName) { this.bookName = bookName;

}

public int getBookId() {

return bookId;

}

public void setBookId(int bookId) { this.bookId = bookId;

}

public String getAuthor() {

return author;

}

public void setAuthor(String author) {

this.author = author;

}

public float getPrice() {

return price;

}

public void setPrice(float price) {

if(price<0.0){

return;

}

this.price = price;

}

//[访问修饰符] 返回值类型 方法名([形参列表]){ }

public String show(){

return String.format("书名__%s 编号__%4d 作者__%s 价格:%.2f",

bookName,bookId,author,price);

}

}

参数传递

参数传递有两种方式:

传值 传引用

传值

传递实参的副本,对实参无影响

基本数据类型及封装类、String属于传值

传引用

传递实参本身,形参的改变影响实参

数组、对象属于传引用

仅讨论一下值传递和引用:

所谓值传递,就是说仅将对象的值传递给目标对象,就相当于copy;系统将为目标对象重新开辟一个完全相同的内存空间。

所谓引用,就是说将对象在内存中的地址传递给目标对象,就相当于使目标对象和原始对象对应同一个内存存储空间。此时,如果对目标对象进行修改,内存中的数据也会改变。

public static void transferParam(int x){

x++;

}

public static void transferParam(Book book){

book.setAuthor("张三丰");

}

public static void main(String[] args) {

int x=10;

System.out.printf("x的值 x=%d%n",x);

transferParam(x);

System.out.printf("x的值没有改变 x=%d%n",x);

Book book=new Book();

System.out.printf("book对象.author:%s%n",book.getAuthor()); transferParam(book);

System.out.printf("book对象.author:%s%n",book.getAuthor()); }

方法重载 方法同名不同参

方法重载是多态性的一种表现形式

1--本类中多个方法同名

2--参数个数,参数类型,参数顺序不同

3--构造方法可重载

注意:方法重载与返回类型无关 即返回类型不同不是重载

public class TestOverloading {

public void doSomething(){

System.out.println("无参的doSomething方法");

}

//形参个数不同

public void doSomething(int x){

System.out.println("doSomething方法接收一个int形参"); }

//形参类型不同

public void doSomething(String str){

System.out.println("doSomething方法接收一个String形参"); }

//形参顺序不同

public void doSomething(String str,int x){

System.out.println("doSomething(String str,int x)"); }

public void doSomething(int x,String str){

System.out.println("doSomething(int x,String str)"); }

public static void main(String[] args) {

TestOverloading obj=new TestOverloading();

obj.doSomething();

obj.doSomething(1000);

obj.doSomething("doSomething");

obj.doSomething(1000, "doSomething");

obj.doSomething("doSomething", 1000);

}

}

构造函数

实例化对象时自动调用的函数

主要作用:

初始化成员变量

说明:

1--与类同名

2--无返回值

3--实例化时自动调用

4--可以重载

声明类时 如果没有指定构造方法 默认有一个无参的构造方法

一旦指定构造函数 默认的构造函数将不再存在

public class Employee {

private String empName;

private int empId;

private short age;

private float salary; // 薪水

private Employee() {

System.out.println("执行无参构造函数"); }

public Employee(int empId) {

this(); //显示调用无参构造函数

System.out.println("执行有参的构造函数"); this.empId = empId;

}

/**

this关键字 表示本类的当前对象

主要用在以下两个地方

1--方法里局部变量与成员变量同名时

2--在构造方法中调用类自身另外的构造方法(位于第一行) */

public Employee(String empName, int empId, short age, float salary) { this(empId);

this.empName = empName;

this.age = age;

this.salary = salary;

}

@Override

public String toString() {

return "Employee [age=" + age + ", empId=" + empId + ", empName=" + empName + ", salary=" + salary + "]";

}

public static void main(String[] args) {

Employee one=new Employee();

System.out.printf("one.empId:%d%n",one.getEmpId());

Employee two=new Employee(100);

System.out.printf("two.empId:%d%n",two.getEmpId());

Employee three=new Employee("东方不败",101,new Short("28"),5000.00F); System.out.println(three); //自动调用toString()

}

}

作业:

1. 编写一个类,该类的对象可以输出大写的所有英文字符

2. 编写一个类 ,该类的对象可以实现查询int类型的值在int数组中的索引值的功能

 

第二篇:第四章Java面向对象的三大特征及高级类特性

第四章小结提纲Java中的继承extends关键字(用它表达继承关系)有继承的代码基本运行顺序(初始化子类必先初始化父类,初始化一个类必先初始化属性.)单继承性(一个类只从继承一个类,Java类的继承只能是单继承的)构造方法不能被继承()super(用来引用该类的父类,规则:1、点取父类中被子类隐藏了的数据成员(属性)。super.s;2、点取已经覆盖了的方法。super.t();3、作为方法名表示父类构造方法。super();)方法的覆盖什么是方法覆盖(子父类方法的名称、返回类型及参数列表完全一样)到底运行哪个方法(new谁就调用谁的方法)覆盖方法的规则(1、覆盖方法的返回类型、方法名称、参数表必须与它所覆盖的方法相同。2、覆盖方法不能比它所覆盖的方法访问性差(即访问权限不允许缩小)public3、覆盖方法不能比它所覆盖的方法抛出更多异常。(throws))方法的重载什么是重载(在同一个Java类中(包含父类),如果出现了方法名称相同,而参数列表不同的情况就叫做重载。参数列表不同的情况包括:个数不同、类型不同、顺序不同等。注意:跟成员方法一样,构造方法也可以重载。)重载的规则(1、方法名称必须相同。2、参数列表必须不同(个数不同,或类型不同、或参数排列顺序不同)。3、方法的返回类型可以相同也可以不相同。)比较覆盖方法和重载方法(覆盖出现在子父类中,重载出现在当前类中)Java中的多态多态是什么(同一行为不同表现形式)多态和类型(只有一个对象,变量却有多个)instanceof(用来判断某个实例变量是否属于某种的类型。)多态对象的类型转换(强制造型)动态绑定static修饰符static修饰符的含义(能够与属性、方法和内部类一起使用,表示是“静态”的。)用static修饰符如何使用(类中的静态变量和静态方法能够与“类名”一起使用)static属性的内存分配(一个类中,一个static变量只会有一个内存空间,虽然有多个类实例,但这些类实例中的这个static变量会共享同一个内存空间。)static属性的初始化(static的变量是在类装载的时候变会被初始化。)static的基本规则(1、一个类的静态方法只能访问静态属性2、一个类的静态方法不能够直接调用非静态方法。3、如访问控制权限允许,static属性和方法可以使用对象名加“.”方式调用;当然也可以使用实例加“.”方式调用。4、静态方法中不存在当前对象,因而不能使用“this”,当然也不能使用“super”,5、静态方法不能被非静态方法覆盖。6、构造方法不允许声明为static的。)静态块(是一个存在与类中方法外面的静态块。静态初始器仅仅在类装载

的时候(第一次使用类的时候)执行一次。)静态importfinal修饰符final修饰符的含义(在Java中声明类、属性和方法时,可使用关键字final来修饰。final所标记的成分具有“终态”的特征,表示“最终的”意思。)final的规则(1、final标记的类不能被继承。2、final标记的类不能被予类(覆盖)重写。3、final标记的变量(成员变量或局部变量)即成为常量,只能赋值一次。4、final标记的成员变量必须在声明的同时赋值,如果在声明的时候没有赋值,那么只有一次的赋值的机会以,而且只能在构造方法中显示赋值,然后才能使用。5、final标记的局部变量可以只声明不赋值,然后再进行一次性的赋值。6、final一般用于标记那些通用性的功能、实现方式或取值不能随意被改变的成分,以避免被误用。)内部类什么是内部类(在一个类(或方法、语句块)的内部定义另一个类)内部类的功能和特点内部类分类(1、类级:成员式,有static修饰2、对象级:成员式,普通,无static修饰3、本地内部类:局部式4、匿名级:局部式)成员式内部类(分类,规则,访问方式)本地内部类匿名内部类Java内存分配方法区(方法区存放装载的类数据信息1、基本信息(定义类时的名字、返回类型、接口、参数列表)2、每个已装载类的详细信息(常量、变量、方法、静态变量等))栈内存(在方法中定义的一些基本类型的变量和对象的引用变量都在方法的栈内存中分配)堆内存(堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。)本地方法栈内存(JNI)String的内存分配---------------------详细课件------------------------------Java中的继承1extends关键字在java里面如何来表达继承的关系呢,就是使用extends关键字,如下:public class A extends B{} 表示A类继承B类,A类自动具有B类允许其能访问的所有变量和属性。继承后的基本运行顺序:规则:初始化子类必先初始化父类。定义父类T1父类第一行 public class T1{父类第二行 {父类第三行 System.out.println("T1的属性");父类第四行 }父类第五行 public T1(){父类第六行 System.out.println("T1的构造方法");父类第七行 }父类第八行 }定义子类T2子类第一行 public class T2 extends T1{子类第二行 {子类第三行 System.out.println("T2的属性");子类第四行 }子类第五行 public T2(){子类第六行 System.out.println("T2的构造方法");子类第七行 }子类第八行 public static void main (String [] args){子类第九行 T2 t = new T2();//创建对象子类第十行 }子类第十一行 }运行顺序如下:首先运

行子类T2的第八行,再运行子类第九行创建对象,创建对象首先要运行子类的构造方法子类的第五行,初始化子类必先初始化父类,运行子类第一行的父类,进入父类的构造方法父类第五行,初始一个类先初始化一个类的属性,再运行父类第三行,再运行父类第六行,运行完父类再运行子类属性子类第三行,再运行子类第六行第1行 public class Test extends Parent{第2行 private String name = "Java私塾";第3行 private int age = 2 ;第4行 public Test(){第5行 age = 1000;//期望能到1000年,第6行 }第7行 public static void main (String[] args){第8行 Test t = new Test();第9行 System.out.println(t.name + "的年龄是" + t.age + "年");第10行 }第11行 }第12行 class Parent{第13行 private int num = 1;第14行 public Parent(){第15行 System.out.println("现在初始化父类构造方法");第16行 }第17行 public void test(){第18行 System.out.println("这是父类的test方法");第19行 }第20行}上述类的基本运行顺序是:(1):先运行第7行,这个程序的入口(2):然后运行第8行,这里要new一个Test,就是调用Test的构造方法。(3):就运行第4行,注意:初始化子类必先初始化父类。(4):要先初始化父类,所以运行第14行。这个父类的构造方法。(5):然后运行第13行,初始化一个类,必须先初始化它的属性。(6):然后运行第15行,(7):然后运行第16行,表示父类初始化完毕;(8):然后回到子类,开始初始化属性,因此运行第2行,然后运行第3行(9):子类属性初始化完过后,才回到子类的构造方法,执行里面的代码,也就是第5行,(10):然后是第6行,表示new一个Test实例完成(11):然后回到main方法中执行第9行(12):然后是第10行运行结果是:现在初始化父类Java私塾的年龄是1000年下面是经过改造后的程序public class Test extends Parent{private String name = "Java私塾";{System.out.println("子类的属性name = Java私塾");}private int age = 2 ;{System.out.println("子类的属性age = 2 ");}public Test(){age = 1000;//期望能到1000年,{System.out.println("子类的构造方法再次初始化age = 1000 ");}}public static void main (String[] args){Test t = new Test();System.out.println(t.name + "的年龄是" + t.age + "年");Parent p = new Parent();p.test();}}public class Parent{private int num = 1;{ System.out.println("父类属性num = 1");}public Parent(){System.out.println("现在初始化父类构造方法");}public void test(){System.out

.println("这是父类的test方法");}}Java中的继承2单继承性单继承性:当一个类从一个唯一的类继承时,被称做单继承性。单继承性使用代码更可靠。Java类的继承只能是单继承的继承不成写成如下形式:public class T2 extends T1 , Test{}构造方法不能被继承尽管一个子类从父类继承所有的方法和变量,但它不继承构造方法,掌握这一点很重要。一个类能得到构造方法,只有两个办法。一种是自己写构造方法,另外一种是根本没有写构造方法,类有一个默认的构造方法。关键字super关键字super可被用来引用该类的父类,它被用来引用父类的成员变量或方法。父类方法被调用,就好像该方法是本类的行为一样,该方法不必有父类中定义,它也可以从某些祖先类中继承。也就是说可以从父类的父类去获取,具有追溯性,一直向上去找,直到找到为止,这是一个重要的特点。super关键字的功能:(1):点取父类中被子类隐藏了的数据成员(属性)(2):点取已经覆盖了的方法。(3):作为方法名表示父类构造方法。super();注:无论是super()还是this();必须写在构造方法第一行。调用父类构造方法在许多情况下,使用默认构造方法来对父类进行初始化。当然也可以使用super来显示调用父类构造方法。例:public class T2 extends T1{public String s = "T2子类的属性222";//在子类中定义属性{System.out.println("T2子类的属性this s =="+this.s);//使用this调用本类的属性}{System.out.println("T1父类的属性super s =="+super.s);//使用super调用父类的属性(点取父类中被子类隐藏了的数据成员)}{System.out.println("如果在子类没有定义的属性只有父类有这个属性name,写成name、this.name、super.name都是指向父类的属性name=="+"name=="+name+",this name=="+this.name+",super name=="+super.name);}{t2(0);//调用本类的方法super.t2(0);//调用父类的方法(点取已经覆盖了的方法)}public void t2(int a){System.out.println("this is T2 zilei de fangfa");}public T2(){super();//调用父类的构造方法,这个是一个空参的隐性调用(作为方法名表示父类的构造方法)System.out.println("T2子类的构造方法");}public static void main (String [] args){T2 t = new T2();}}public class T1{public String s = "T1父类的属性111";public String name = "父类的name";{System.out.println("T1父类的属性");}public T1(){System.out.println("T1父类的构造方法");}public void t2(int a){System.out.println("this is T1 fulei de fangfa");}}+++++++++++++

++++++++++++++++++++++++++++++++++++++++ 方法的覆盖1(是什么)什么是方法的覆盖(Overridden Methods)在父子类中,如果子类某个方法的名称、返回类型及参数列表正好与父类中某个方法完全一样,那么这个方法就是覆盖方法,子类覆盖子父类的方法。例子:public class T extends Parent{public void t1(int a,int b,String c){System.out.println("this is T.t1");}public static void main(String [] args){T t = new T();//实例化子类的Tt.t1(1,1,"");Parent t1 = new T();//多态向上造型,子类可以向上造型父类,但实例你给的还是子类。t1.t1(1,1,"");Parent t2 = new Parent();//实例化父类,t2.t1(1,1,"");}}//父类class Parent{public void t1(int a, int b, String c){System.out.println("this is P.t1!!");}} 上方子类与父类有共同的方法t1,那么T t= new T();t.t1(1,1"");是运行的哪个方法呢。事实上,你得到与变量的运行时类型相关的行为,而不是与变量的编译时类型相关的行为。这是面向对象语言的一个重要特征,它也是多态性的一个特征,并通常被称作虚拟方法调用或动态绑定或后期绑定。***************************************************** 因此规则是:编译时看数据类型,运行时看实际的对象类型(即new操作符后跟的构造方法是哪个类的)。一句话:new谁就调用谁的方法******************************************************方法的覆盖2(有什么)*******************************************************覆盖方法的规则:(1):覆盖方法的返回类型、方法名称、参数表必须与它所覆盖的方法相同。(2):覆盖方法不能比它所覆盖的方法访问性差(即访问权限不允许缩小)public(3):覆盖方法不能比它所覆盖的方法抛出更多异常。(throws)*******************************************************例:public class T extends Parent{//子类要么不抛异常,要么抛出 NullPointerException,AithmeticException这两个异常public void t1(int a,int b,String c){System.out.println("this is T.t1");}public static void main(String [] args){T t = new T();//实例化子类的Tt.t1(1,1,"");Parent t1 = new T();//多态向上造型,子类可以向上造型父类,但实例你给的还是子类。t1.t1(1,1,"");Parent t2 = new Parent();//实例化父类,t2.t1(1,1,"");}}//父类class Parent{//抛出异常public void t1(int a, int b, String c) throws NullPointerException,ArithmeticException{System.out.println("this is P.t1!!");}}+++++++++++++++++++++++++++++++++++++++++++++++++++++++方法的重载1(什么是重载)在同一个Java类中(包含父类),如果出现了方法名称相同,而参数列表不同的情况就叫

做重载。参数列表不同的情况包括:个数不同、类型不同、顺序不同等。特别提示:仅仅参数变量名称不同是不可以的。注意:跟成员方法一样,构造方法也可以重载。例public class T extends Parent{public void t1(int a,int b,String c){System.out.println("this is T.t1");}public static void main(String [] args){T t = new T();//实例化子类的Tt.t1(1,1,"");Parent t1 = new T();//多态向上造型,子类可以向上造型父类,但实例你给的还是子类。t1.t1(1,1,"");Parent t2 = new Parent();//实例化父类,t2.t1(1,1,"");T t4 = new T();t4.t2();T t5 = new T();//方法重载的调用是根据参数列表来区分的t5.t1(2);}public void t2(){super.t1(1,1,"");//通过关键字super调用父类的相同的方法}//下面就是t1的方法重载public int t1(int a){System.out.println("方法重载返回一个int 0");return 0;}}//父类class Parent{public void t1(int a, int b, String c) throws NullPointerException,ArithmeticException{System.out.println("this is P.t1!!");}}*******************************************************方法的重载的规则:(1):方法名称必须相同。(2):参数列表必须不同(个数不同,或类型不同、或参数排列顺序不同)。(3):方法的返回类型可以相同也可以不相同。注意:调用语句的参数表必须有足够的不同,以至于允许区分出正确的方法被调用。正常的拓展晋升(如,单精度类型ffloat到双精度类型double)可能被应用,但是这样会导致在某些条件下的混淆*******************************************************Java中的多态1多态是什么:多态是同一个行为具有多种不同的表现形式或形态的能力.在Manager继承Employee的情况下,一个Employee既可以是一个普通的Empployee类,也可以是一个Manager类.也就是说下述表示都是对的Employee e = new Employee();Employee e = new Manager();从上面可以看到:同一个行为Employee具有多个不同的表现形式(既可以是一个普通的Employee类,也可以是一个Manager类),这就被称为多态.注意:方法没有多态的说态,严格说多态是类的特性.但是也有对方法说多态的.了解一下,比如前面学到的方法覆盖称为动态多态,是一个运行时问题;方法重载称为静态多态,是一个编译时问题.多态与类型一个对象只有一个格式(是在构造时给它的).但是,既然变量能指向不同格式的对象,那么变量就是多态性的.也就是说:一个对象只有一个形式,但一个变量却有多种不同形式.象大多数面向对象语言一样,Java实际上允许父类类型的引用变量指向一个子类的对象。因此可以说:Employee e = new Manager();使用变量e是因为你能访问的对象部

分只是Employee的一部分,Manager的特殊部分是隐藏的。这是因为编译都应意识到,e是一个Employee,而不是一个Manager因而,下述情况是不允许的:e.dapartment = "Finance";//非法的,编译时会出错可能有人会不理解,为什么明明是new的一个Manager,却不能访问Manager的属性数据,原因在于编译的时候,变量e是一个Employee的类型,编译器并不去管运行时e指向的具体对象是一个Employee的对象,还是一个Manager的对象,所以它只能访问到Employee里面定义的属性和方法。所以说编译时看数据类型。那么想要访问到Manager里面的department该怎么办呢?这就需要先对e进行强制类型转换,把它还原成为Manager类型,就可以访问到Manager里面的属性和方法了。如下:Employee e = new Manager();Manager m = (Manager)e;m.department = "开发部";//这就是合法的了。instanceof运算符功能用来判断某个实例变量是否属于某种的类型。if (t1 instanceof T){}如果t1属于T的类型,那么就进行转换,如果不是,则不转换多态对象的类型转换向上强制类型转换类层次总是允许的,而且事实上不需要强制类型转换运算。可由简单的赋值实现。严格讲不存在向下类型转换,其实就是强制类型转换,编译器必须满足类型转换至少是可能的这样的条件。*******************************************************java中造型:1、自动升级造型,2、强制类型转换,3、表达式升级,4、向上造型*******************************************************什么是绑定:将一个方法调用 同 一个方法主体连接到一起就称为“绑定”(Binding)什么是动态绑定方法调用和方法体在运行时刻的连接就称之为动态绑定(dynamic binding).后期绑定,它意味着绑定在运行期间进行,以对象的类型为基础。后期绑定也叫作“动态绑定”或“运行期绑定”。若一种语言实现了后期绑定,同时必须提一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:它们都要在对象中安插某些特殊类型的信息。Java中绑定的所有方法都采用后期绑定技术,除非一个方法已被声明成final。这意味着我们通常不必决定是否应进行后期绑定--它是自动发生的。++++++++++++++++++++++++++++++++++++++++++++++++++++++修饰符1static修饰符static修饰符能够与属性、方法和内部类一起使用,表示是“静态”的。类中的静态变量和静态方法能够与“类名”一起使用。不需要创建一个

类的对象来访问该类的静态成员。所以static修饰的变量又称作“类变量”。这与实例变量不同。实例变量总是用对象来访问,因为它们的值在对象和对象之间有所不同。例如:public class T6{public static String s = "Java私塾";public static void main(String[] args){System.out.println("s==="+T6.s);//静态属性不用new可以用类名直接调用a();//静态方法的调用T6.a();}public static void a(){System.out.println("aaaaaaaa");}}******************************************************变量有四级别:类级属性,类变量,方法变量******************************************************static属性的内存分配一个类中,一个static变量只会有一个内存空间,虽然有多个类实例,但这些类实例中的这个static变量会共享同一个内存空间。public class T6{public static String s = "Java私塾";public static void main(String[] args){System.out.println("s==="+T6.s);//静态属性不用new可以用类名直接调用a();//静态方法的调用T6.a();T6 t1 = new T6();T6 t2 = new T6();t2.s = "hahaha!!";System.out.println("t1.s==="+t1.s+",t2.s=="+t2.s+",T6.S=="+T6.s);//值都为“hahaha!!”说明多个实例指向同一个内存空间。}public static void a(){System.out.println("aaaaaaaa");}}static属性变量初始化static的变量是在类装载的时候变会被初始化。也就是说,只要类被装载,不管你是否使用了这个static变量,它都会被初始化。*******************************************************static的基本规则1、一个类的静态方法只能访问静态属性2、一个类的静态方法不能够直接调用非静态方法。3、如访问控制权限允许,static属性和方法可以使用对象名加“.”方式调用;当然也可以使用实例加“.”方式调用。4、静态方法中不存在当前对象,因而不能使用“this”,当然也不能使用“super”,5、静态方法不能被非静态方法覆盖。6、构造方法不允许声明为static的。注:非静态变量只限于实例,并只能通过实例引用被访问。******************************************************静态初始器--静态块静态初始器(Static Initializer)是一个存在与类中方法外面的静态块。静态初始器仅仅在类装载的时候(第一次使用类的时候)执行一次。静态初始器的功能是:通常用来初始化静态的类属性。在类属性中加一个public class T7{public static String s = "Java私塾";static{//静态属性块,在类装载时只执行一次System.out.println("static 123");}{//非静态属性块,每次实例化时都执行一次。System.out.println("123");}public static void main(String[] args){T7 t = new T7();T7 t1 = n

ew T7();T7 t2 = new T7();}}静态import(供了解)当我们要获取一个随机数时,写法是:double randomNum = Math.random();可以使用静态import写为:import static java.lang.Math.random;double randomNum = random();静态引用使我们可以象调用本地方法一样调用一个引入的方法,当我们需要引入同一个类的多个方法时,只需写为“import static java.lang.Math.*”即可。这样的引用方式对于枚举也同样有效.+++++++++++++++++++++++++++++++++++++++++++++++++++++++final修饰符什么是final修饰符在Java中声明类、属性和方法时,可使用关键字final来修饰。final所标记的成分具有“终态”的特征,表示“最终的”意思。*******************************************************final的具体规则1、final标记的类不能被继承。2、final标记的类不能被予类(覆盖)重写。3、final标记的变量(成员变量或局部变量)即成为常量,只能赋值一次。4、final标记的成员变量必须在声明的同时赋值,如果在声明的时候没有赋值,那么只有一次的赋值的机会以,而且只能在构造方法中显示赋值,然后才能使用。5、final标记的局部变量可以只声明不赋值,然后再进行一次性的赋值。6、final一般用于标记那些通用性的功能、实现方式或取值不能随意被改变的成分,以避免被误用。说明:1、如果将引用类型(即任何类的类型)的变量标记为final,那么该变量不能指向任何其它对象。但可以改变对象的内容,因为只有引用本身是final的。2、final除了可以使用在类定义、属性上、方法上外,还可以用于方法内部,比如参数列表或者局部变量都是可以的。public final class A{public final void t1(final String a ,fianl int b){final String c = "123";}}******************************************************内部类(供了解)什么时内部类在一个类(或方法、语句块)的内部定义另一个类,后者称为内部类,有时也称为嵌套类(Nested Classes)内部类特点1、内部类可以体现逻辑上的从属关系。同时对于其他类可以控制内部类对外不可见等。2、外部类的成员变量作用域是整个外部类,包括内部类。但外部类不能访问内部类的private成员3、逻辑上相关的类可以在一起,可以有效的实现信息隐藏。4、内部类可以直接访问外部类的成员。可以用此实现多继承。5、编译后,内部类也被编译为单独的类,不过名称为outclass$inclass的形式。示例如下:public class Outer{private int size;public class Inner{private int counter = 10;public void doStuff(){size++;}}public static void main (String[] args){Outer outer = new Outer();

Inner inner = outer.new Inner();//当做实例的方法使用inner.doStuff();System.out.println(outer.size);System.out.println(inner.counter);//System.out.println(counter);编译错误,外部类不能访问内部类的private变量}}注意:outer.new Inner()这样的语法,其实是因为对于Outer类来说,Inner类相当于是一个成员类,所以不能直接访问,应该用实例变量点取。如果把Inner类定义成static的,那么就可能直接Inner inner = new Inner();了。内部类的分类:内部类按照使用上可以分为四种情形:1、类级:成员式,有static修饰2、对象级:成员式,普通,无static修饰3、本地内部类:局部式4、匿名级:局部式成员式内部类public class Outer1{private int size;public class Inner{public void dostuff(){size++}}}成员式内部类如同外部类的一个普通成员。成员式内部类的基本规则1、可以有各种修饰符,可以用4种权限、static、final、abstract定义(这点和变通的类是不同的);2、若有static限定,就为类级,否则为对象级。类级可以通过外部类直接访问,对象级需要先生成外部的对象后才能访问。3、内外部类不能同名4、非静态内部类中不能声明任何static成员5、内部类可以互相调用,如下:class A{class B{}//B、C间可以互相调用class C{}}public class Outer{private int size;public class Inner{public int counter = 10;public void doStuff(){size++;}}public class Inner2{public void doStuff(){Inner t = new Inner();//内部类直接newSystem.out.println(t.counter);}}public static void main (String[] args){Outer outer = new Outer();Inner2 inner = outer.new Inner2();//当做实例的方法使用inner.doStuff();}}成员式内部类的访问内部类访问外层类对象的成员时,语法为:“外层类名.this.属性”。使用内部类时,由外部类对象加“.new”操作符调用内部的构造方法创建内部类的对象.1、在另一个外部类中使用非静态内部类中定义的方法时,要先创建外部类的对象,再创建与外部类相关的内部类的对象,再调用内部类的方法,如下所示:class Outer2{private int size;class Inner{public void dostuff(){size++;}}}class TestInner{public static void main(String[] args){Outer2 outer = new Outer2();Outer2.Inner inner = outer.new Inner();inner.dostuff();}}2、static内部类相当于其外部类的static成分,它的对象与外部类对象间不存在依赖关系,因此可直接创建。示例如下:class Outer2{private static int size;static class Inner{public void dostuff(){size++;System.out.println("size=="+size);}}}public

class Test{public static void main (String[] args){Outer2.Inner inner = new Outer2.Inner();inner.dostuff();}}3、由于内部类可以直接访问其外部类的成分,因些当内部类与其外部类中存在同名属性或方法时,也将导致命名冲突。所以在多层调用进要指时,如下所示:public class Outer3{private int size;public class Inner{private int size;public void dostuff(int size){size++;//本地的size;this.size;//内部类的sizeOuter3.this.size++;//外部类的size}}本地内部类本地类(Local class)是定义在代码块中的类,它们只在定义它们的代码块中是可见的。本地类有几个重要特性1、仅在定义了它们的代码块中是可见的。2、可以使用定义它们的代码块中的任何本地final变量3、本地类不可以是static的,里边也不能定义static成员。4、本地类不可以用public\private\protected修饰,只能使用缺省的。5、本地类可以是abstract的示例如下:public final class Outter{public static final int TOTAL_NUMBER = 5;public in id = 123;public void t1(){final int a = 15;String s = "t1";class Inner{public void innerTest(){System.out.println(TOTAL_NUMBER):System.out.println(id);System.out.println(a);//System.out.println(s);不合法,只能访问本地方法的final变量}}new Inner().innerTest();}}匿名内部类是什么?匿名内部类是本地内部类的一种特殊形式,也就是没有类名的内部类,而且具休的类实现会写在这个内部类里面,把上面的例子改造一下,如下所示:public final class Test{public static final int TOTAL_NUMBER = 5;public int id = 123;public void t1(){final int a = 15;String s = "t1";new Aclass(){public void testA(){System.out.println(TOTAL_NUMBER);System.out.println(id);System.out.println(a);//System.out.println(s);不合法,只能访问本地方法final变量}}.testA();}}class Aclass{public void testA(){}}注意:匿名内部类是在一个语句里面,所以后面需要加“;”匿名类的规则1、匿名类没有构造方法2、匿名类不能定义静态的成员3、匿名类不能用4种权限static final abstract修饰4、只可以创建一个匿名类实例如下示例public class Test{public Contents getCont(){return new Contents(){private int i =11;public int value(){return i;}};}public static void main(String[] args){Test p = new Test();Contents c = p.getCont();System.out.println("dd"+c.value());}}class Contents{public int value(){return 0;}}+++++++++++++++++++++++++++++++++++++++++++++++++++++++再谈Java的内存分配1Java程序运行时的内存结构分成:方法区、栈内存、堆内存

、本地方法栈几种。栈和堆都是数据结构的知识,如果不清楚,没有关系,就当成一个不同的名字就好了,下面的讲解不需要用到它们的具体的知识。方法区方法区存放装载的类数据信息包括:1、基本信息(定义类时的名字)1)每个类的全限定名2)每个类的直接超类的全限定名(可约束类型转换)3)该类是类还是接口4)该类型的访问修饰符5)直接超接口的全限定名的有序列表2、每个已装载类的详细信息:1)运行时常量池 :存放该类型所用的一切常量(直接常量和对其它类型、字段、方法的符号引用),它们以数组形式通过索引被访问,是外部调用与类联系及类型对象化的桥梁,它是类文件(字节码)常量池的运行时表示。(还有一种静态常量池,在字节码文件中)。2)字段信息:类中声明的每一个字段的信息(名,类型,修饰符)。即变量3)方法信息:类中声明的每一个方法的信息(名,返回类型,参数类型,修饰符,方法的字节码和异常表)。4)静态变量5)到类classloader的引用:即到该类的类装载器的引用6)到类class的引用:虚拟机为每一个被装载的类型创建一个class实例,用来代表这个被装载的类。栈内存Java栈内存以帧的形式存放本地方法的调用状态(包括方法调用的参数,局部变量,中间结果等)。也就是说:在方法中定义的一些基本类型的变量和对象的引用变量都在方法的栈内存中分配栈内存的构成Java栈内存由局部变量区、操作数栈、帧数据区组成。1)局部变量区为一个以字为单位的数组,每个数组元素对应一个局部变量的值。调用方法时,将方法的局部变量组成一个数组,通过索引来访问。若为非静态方法,则加入一个隐含的引用参数this,该参数指向调用这个方法的对象。而静态方法则没有this参数。因此,对象无法调用静态方法。2)操作数栈也是一个数组,但是通过栈操作来访问。所谓操作数是那些被指令操作的数据。当需要对参数操作时如a=b+c,就将即将被操作的参数压栈,如将b和c压栈,然后由操作指令将它们弹出,并执行操作。虚拟机将操作数栈作为工作区。3)帧数据区处理常量池解析,异常处理等。堆内存堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。引用变量就相当于是为

数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。栈内存和堆内存比较栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是:存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(int,short,long,byte,float,double,boolean,char)和对象句柄。栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:int a = 3;int b = 3;编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没有找到,就将3存放进业,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3.这样,就出现了a与b同时均指向3的情况。这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的必变不会影响到b的值。要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b,它是由编译器完成的,它有利于节省空间。本地方法栈内存Java通过Java本地接口JNI(Java Native Interface)来调用其它语言编写的程序,在Java里面用native修饰符来描述一个方法是本地方法。这个了解一个就好了,在我们的课程中不会涉及到。String的内存分配 String是一个特殊的包装类数据。可以用:String str = new String("abc");String str = "abc";两种形式来创建,第一种是用new()来新建对象的,它会在存放堆中。每调用一次就会创建一个新的对象.而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向"abc",如果已经有"abc"则直接令str指向"abc".比较类里面的数值是否相等时,用equals()方法,当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子说时上面的理论.public class T8{public static void main (String[] args){String s1 = "abc";String s2 = "abc";System.out.println(s1==s2);//true同时指向栈内存里的同一个对象的.String s3 = new String("abc");String s4 = new String("abc");System.out.println(s3==s4);//false用new的方式生成不同的对象.每一次生成一个.System.out.println(s1==s3);//false}}因此用第一种方式创建多个"abc"字符串,在内存中其实只存在一个对象而已,这种写法有利于节省内存空间.而通过new()方法创建String,每次都创建一个新的对象.由于Stri

ng类的值不可变性(immutable),当String变量需要经常变换其值时,应该考虑使用StringBuffer或StringBuilder类,以提高程序效率.++++++++++++++++++++++++++++++++++++++++++++++++++++++

相关推荐