初识JAVA---深入了解JAVA特性(5)

基本类型(primitive type):其值存在于变量中。

引用型(reference type)的变量除了占据一定的内存空间外,它所应用的对象实体(由new创建),也要占据一定的空间。

 

字段变量存在于类中

局域变量是方法中定义的变量或方法的参变量

 

从内存角度

 存储位置不同  字段变量是对象的一部分,存在于堆中,局部变量是存在于栈中

 生命周期不同  字段变量是随着对象的存在而存在    局部变量是随着方法调用的存在而存在

 初始值  字段变量可以自动赋值,局部变量则可以显式赋值

 

语法角度

字段属于类,可以用public private static final修饰     static表示全局的或者说是静态的不属于对象实体的

局部变量不能够被访问控制符及static修饰

都可以被final修饰

 

变量的传递

调用对象方法时,需要传递参数。

Java是值传递,将表达式的值赋值给形式参数    不改变原来变量的值    相当于C语言中形式参数

对于引用型变量,传递的值是引用值,而不是赋值对象实体     可以改变对象的属性  也就是C中的指针传递进去改变了传递的变量的值了

 

变量的返回

方法的返回:

       返回基本类型

       返回引用类型。可以存取对象实体

Object getNewObject()
{
Object obj=new Object();
return obj;
}
调用时:Object p=getNewObject();

多态

所谓多态,函数的多态,就是相同名字的函数,可以同时存在(它们的传递参数不同)

多态由两种情形:

编译时多态:重载(overload)(多个同名的不同方法)

                    如:p.sayHello();p.sayHello("Wang");

运行时多态:覆盖(override)(子类对父类方法进行覆盖 )

                     动态绑定(dynamic binding)...虚方法调用(virtual method invoking)

                     调用方法时,程序会正确的调用子类对象的方法

多态的特点大大提高了程序的抽象程度和简洁性

 

上溯造型(upcasting)

        把派生类当作基本类型处理

Person p=new Student();

这个person的引用,可以引用到一个student对象的父类对象,因为student时person的一个子类,所以这种引用时上溯造型

void fun(Person p){...}    fun(new Person());

上溯造型带来了另一个问题  我们实际传进去的参数的类型改变了  例如上面这个函数   person的子类都可以进来变成person类型

那它在运行的时候调用哪个呢?就是用虚方法来调用的

 

虚方法调用

TestVirtualInvoke.java

用虚方法调用,可以实现运行时多态!

   子类重载父类方法时,运行时,系统根据改调用方法的实例类型拉力决定选择哪个方法调用,所有的非final方法都会自动地进行动态绑定  

不做声明,它自动就时动态的绑定

class Shape{
    void draw(){System.out.println("Shape Drawing");}
}
class Circle extends Shape{
    void draw(){System.out.println("Draw Circle");}
}
class Triangle extends Shape{
    void draw(){System.out.println("Draw Three Lines");}
}

void doStuff(Shape s)
{
    s.draw();
}
Circle c=new Circle();
Triangle t=Triangle();
Line I=new Line();
doStuff(c);
doStuff(t);
doStuff(I);
//结果  Draw Circle  Draw Three Draw Line

上面这个代码是来体现虚方法的自动性  花里胡哨的的  

从内存的角度来看,doStuff(c)它的参数是引用,所以里面的值就是调用了c  所以s.draw()就是执行c.draw()

 

Java中普通的方法是虚方法,但static private方法不是虚方法调用

static private与虚方法编译后用的指令是不同的

三种非虚的方法

static的方法,以声明的类型为准,与实例无关

private方法 子类看不见,也不会被虚化

final方法 子类不能覆盖,不存在虚化问题

首页博客学院下载论坛问答活动专题招聘APPVIP会员
Python进阶之路

写博客

Markdown编辑器
富文本编辑器
我的主页

文章管理
评论管理
分类专栏
订阅专栏
博客搬家

博文数据统计Beta版
百度热搜词条
自定义百度统计
等级权益

订单收益
博客打赏

博客设置
博客模块管理
自定义域名

CSDN博客交流群

打开手机QQ扫码
或点击这里加入群聊


QQ客服

初识JAVA---深入了解JAVA特性(5) 
 23/100

文章标签:
添加标签
最多添加5个标签

分类专栏:
JAVA
添加新分类
最多添加3个标签,#为二级分类

资源信息:
请填写资源链接
 上传资源
文章类型:
 *
 申请原创将启用(Creative Commons )版权模板,如果不是原创文章,请选择转载或翻译 原创文章默认开启打赏, 打赏管理
发布形式:
  


class Shape{
    static void draw(){System.out.println("Shape Drawing");}
}
class Circle extends Shape{
    static void draw(){System.out.println("Draw Circle");}
}
class Triangle extends Shape{
    static void draw(){System.out.println("Draw Three Lines");}
}

void doStuff(Shape s)
{
    s.draw();
}
Circle c=new Circle();
Triangle t=Triangle();
Line I=new Line();
doStuff(c);
doStuff(t);
doStuff(I);
//结果  Shape Drawing   Shape Drawing   Shape Drawing 
因为有static的修饰  在调用doStuff的时候,s被Shape修饰了   static  只与修饰的类有关于实际对象无关
 

 对象构造于初始化

对象的构造都是通过构造方法来实现的(constructor)

     对象都有构造方法

     如果没有 百年一起会加一个default的构造方法

调用本类或父类的构造方法

     this调用本类的其他构造方法

     super调用直接父类的构造方法

     this 或super要放在第一条语句,且只能够有一条

如果没有this  super   则编译器自动加上super(),即直接调用父类不带参数的构造方法

因为必须令所有父类的构造方法都得到调用,否则整个对象的构建就可能不正确

 

class ConstrctCallThisAndSuper
{
    public static void main(String[] args)
        {
         Person p= new Graduate();
        }
}

class Person{
    String name;
    int age;
    Person(){}
    Person(String name,int age){
        this.name=name;this.age=age;
        System.out.println("In Person(String,int)");
    }
}
class Student extends Person{
    String school;
    Student(){
        this(null,0,null);
        System.out.println("In Student()");
        }
    Student(String name,int age,String school){
        super(name,age);
        this.school=school;
        System.out.println("In Student(String,int,String)");
        }
}
class Graduagte extends Student
{
    String teacher="";
    Graduate(){
        //super();//如果没有this super 编译器会自动加上super()调用父类不带参的构造方法
        System.out.println("In Graduate()");
        }
}
运行结果
In Person(String,int)
In Student(String,int,String)
In Student()
In Graduate()
解读    一开始main函数中只构造了一个对象Person p= new Graduate();
        由于它没有this,super,所以系统默认执行父类的构造函数
        在Student中,默认构造函数调用this(null,0,null)
        所以执行student(null,0,null) ,第一句是super(name,age) 所以取父类中找对应的构造函数                        
        找到Person执行Person(nage,age)
        所以输出In Person(String,int),返回student(null,0,null);
        输出In Student(String,int,String),Student()默认构造函数中
        输出In Student()
        最后返回Graduate()的构造函数
        输出In Graduate()
问题举例
Class A
{
    A(int a){}
}
Class B extends A{
    B(String s){}//编译不能通过
}
因为B继承了A类  在B中没有this super 语句 
所以编译器会自动加上  super()
但是A中的构造方法不存在无参数的构造方法,所以编译出错

解决方法:
在A中加一个A(){}这样就可以了

 

创建对象时初始化

p=new Person(){{age=18;name="李明";}};

这样可以针对没有相应的构造函数,但又赋值   注意双括号

 

构造方法的执行过程

        调用本类或父类的构造方法,直至最高一层(Object);

        按照声明顺序执行字段的初始化赋值

        执行构造函数中的各语句

简单说,先父类构造,再本类成员赋值,最后执行构造方法中的语句

 

垃圾回收机制

对象回收是由Java虚拟机的垃圾回收线程来完成的(在内部,任何对象都有一个引用计数器,当计数器的值是0的时候,说明该对象可以回收)

String method(){
String a,b;
a=new String("hello world");
b=new String("game over");
System.out.println(a+b+"Ok");
a=null;
a=b;
return a;
}

Java 没有析构方法,但Object的finalize()有类似功能

        系统再回收时自动调用对象的finalize()方法

        protected void finalize() throws  Throwable{}

子类的finalize()方法

       可以再子类的finalize()方法中应该调用父类的finalize()方法 以保证父类的清理工作能够正常进行

 

由于finalize()方法的调用时机并不确定,一般不用finalize()

关闭打开的文件,清楚一些非内存资源等工作需要进行处理

可以使用 try-with-resources语句(java7以上)

(可以直观的理解试着用用,用完就关 ,一般用于关闭网络、文件等)

对于实现了java.lang.AutoCloseable的对象

try(Scanner scanner=new Scanner(...)){

...//这里面不管是异常的还是其他都会尝试去执行

}

会自动调用close()方法相当于

finally{

Scanner.close();

}    

 

内部类

       将类的定义 class xxxx{...}置入一个类的内部即可

       编译器生成xxx$xxx这样的class文件

       内部类不能够与外部类同名

内部类的使用

       在封装它的类的内部使用内部类,与普通类的使用方式相同

       其他地方使用

               类名前面要冠以外部类的名字

              在用new创建内部类时,也要在new前面冠以对象变量

                  外部对象名.new 内部类名(参数)

 

下面举一个内部类的例子    Contents 和Destination 都是内部类

class TestInnerClass{
    public static void main(String[] args){
        Parcel p=new Parcel();
        p.testShip();

        Parcel.Contents c=p.new Contents(33);
        Parcel.Destination d=p.new Destination("Hawii");
        p.setProperty(c,d);
        p.ship()
    }    
}


class Parcel{
    private Contents c;
    private Destination d;
    class Contents{
        private int i;
        Contents(int i){this.i=i;}
        int value(){return i;}
    class Destination{
        private String label;
        Destination(String whereTo){label=whereTo;}    
        String readLabel(){return label;}
    }
    void setProperty(Contents c,Destination d){
        this.c=c;this.d=d;
    }
    void ship(){
        System.out.println("move"+c.value()+"to"+d.readLabel());
    }
    public void testShip(){
        c=new Contents(22);
        d=new Destination("Beijing");
        ship();
    }
}

内部类可以直接访问外部类的字段及其方法,即使private也行

如果内部类的字段和外部类重名了,调用外部类方法的时候使用  外部类名.this.字段或方法

用static修饰内部类,表明该内部类实际是外部类,因为它与外部列的实例无关。

static类在使用时,

       实例化static类时候,在new前面不需要用对象实例变量

       static类中不能访问其外部类的非static的字段及方法,即只能够访问static成员

       static方法中不能访问非static的域及方法,也不能够不带前缀地new一个非static的内部类

 

public static void main(String[] args)
{
    A.B a_b=new A().new B();
    A a=new A();
    A.B ab=a.new B();
    Outer.Inner oi=new Outer.Inner();//由于这个内部类是static所以和上面两个定义方法不同
}
class A
{
    private int x;
    void m(){
        new B();
    }
    static void sm(){}
    class B
    {
        B(){x=5;}
    }
}

局部类  在一个方法中 也可以定义类

class Outer
{
    private int size=5;
    public Object makeTheInner(int localVar)
    {
        final int finalLocalVar=99;
        class Inter{
            public String toString(){
                return("InnerSize:"+size+"finalLocalVar:"+finalLocalVar);
            }
        }
    }
    return new Inner();
}

同局部变量一样,方法中的内部类  不能够用public private protected static修饰  但可以用 final或者abstract修饰

可以访问其外部类的成员

不能够访问该方法的局部变量,除非是final局部能量,在上面程序的例子中,我们方法里定义的类可以访问size  如果finalLocalVar前面没有final,它就不能访问了

 

匿名类:一种特殊的内部类。没有类名,定义类的时候就生成该对象的一个实例,一次性使用的类

class Outer
{
    private int size=5;
    public Object makeTheInner(int localVar)
    {
        final int finalLocalVar=99;
        return new Object()
            {
            public String toString()
                {
                return("InnerSize:"+size+"finalLocalVar"+finalLocalVar);
                }
            };
        }
    }
    return new Inner();
}

匿名类的使用:不取名字,直接使用父类或接口的名字

                         类定义的时候就创建实例,类的定义前有一个new

                         在构造对象时使用父类构造方法,它不能定义构造方法,因为它没有名字,如果new对象时候,要带参数,使用父类构造方法

 

匿名类的用处:

用到界面的事件处理

       注册一个事件侦听器

      

//SymAction ISymAction=new SymAction();  
//btn.New.addActionListener(ISymAction);

btnNew.addActionListener(new ActionListener(){
    public void actionPerformed(ActionEvent event)
    {
        btnNew_ActionPerformed(event);    
    }
});
比如图形界面按一个按钮,第一行注释的需要先new一个对象,在来监听它,一般这个对象只用一次。
下面这个改写,相当于在方法中的类,而且是匿名类,用完就没事了,用一次

作为方法的参数

       排序,给一个比较大的接口

Arrays.<Book>sort(books,new Comparator<Book>(){
        public int compare(Book b1,Book b2){
             return b1.getPrice()-b2.getPrice();
             }        
});

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值