精华内容
下载资源
问答
  • js的晚绑定和极晚绑定

    千次阅读 2014-01-03 16:05:31
    js的晚绑定和大多数语言(比如c++)的晚绑定概念一样,简单的说,就是动态地引用不同的实例的同名方法(或属性),例如代码:  123456 window.a = function() {}; a.prototype....
    js中的晚绑定和大多数语言(比如c++)中的晚绑定概念一样,简单的说,就是动态地引用不同的实例的同名方法(或属性),例如代码: 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • window.a = function() {};
    • a.prototype.method = function() {alert("a");};
    • window.b = function() {};
    • b.prototype.method = function() {alert("b");};  
    • c = new window[prompt("")];
    • alert(c.method());
    当运行时,用户在输入框里输入a,那么最后提示的就是a,而输入b,提示的就是b,这就是晚绑定。
    而js中,还有一种叫做“极晚绑定” ,很少语言有支持极晚绑定。而js得prototype链机制,导致了js支持极晚绑定。示例代码如下:
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • var a = function() {};
    • a.prototype.p1 = 1;
    • var b = new a();
    • alert(b.p1)// 1
    • alert(b.p2)// undefined
    • a.prototype.p2 = 2;
    • alert(b.p2)// 2
    b初始化a的一个实例,此时输出b.p1,根据prototype链接,结果是1。而第一次输出b.p2时,显示的 undefined。然后,再设置a.prototype.p2=2,此时在输出b.p2,显示的是2。所有这些就是prototype链在作怪。因为, 访问b.p1和b.p2都不是真正访问对象b中的p1属性和p2属性(因为没有语句采取b.p1=xx;b.p2=xx;来设置的对象b的属性),访问的 都是b对象沿着prototype链上的p1和p2属性,即都是a.prototype.p1和a.prototype.p2,所以在b初始化后,再设置 a.prototype.p2,就使得能够通过b.p2来访问p2属性。
    展开全文
  • WPF的数据绑定--元素绑定

    千次阅读 2019-04-30 11:58:21
    因此当源对象改变依赖属性的值时,会立即更新目标对象绑定属性。 绑定表达式 当使用绑定表达式时,不必对源对象做任何改动,只需配置源对象使其属性具有正确的值范围。 <Slider Grid.Row="0" Name=...

    扣扣技术交流群:460189483 

    1. 元素绑定

    数据绑定最简单的形式是源对象是WPF元素而且源属性是依赖项属性。依赖项属性具有内置的更改通知支持。因此当源对象中改变依赖属性的值时,会立即更新目标对象中的绑定属性。

    绑定表达式

    当使用绑定表达式时,不必对源对象做任何改动,只需配置源对象使其属性具有正确的值范围。

    <Slider Grid.Row="0" Name="sliderFontSize" Margin="3" Minimum="1" Maximum="40" Value="10" TickFrequency="1" TickPlacement="TopLeft"> 
    </Slider>
    <TextBlock Grid.Row="1" Margin="10" Text="Simple Text" Name="lblSimpleText"FontSize="{Binding ElementName=sliderFontSize,Path=Value}">   
    </TextBlock>
    

    元素绑定的方式是:属性 = "{Binding ElementName=绑定源,Path=属性}"  

    绑定错误

    WPF不会引发异常来通知与数据绑定相关的问题。如果指定的元素或属性不存在,那么不会收到任何的指示;相反,只是不能在目标属性中显示数据。

    调试可通过Visual Studio的OutPut窗口查看,WPF会输出绑定细节的跟踪信息。

    绑定模式

    名称说明
    OneWay当源属性变化时更新目标属性。
    TwoWay当源属性变化时更新目标属性,并且当目标属性变化时更新源属性。
    OneTime最初根据源属性设置目标属性,然而,其后的所有改变都会被忽略。通常如果知道属性不会变化,可通过这种模式降低开销。
    OneWayToSource与OneWay相反,当目标属性变化时更新源属性。
    Default此类绑定依赖于目标属性,既可以是双向的,也可以是单向的。除非明确指定了一种绑定模式,否则所有绑定使用该方法

    使用代码创建绑定

    Binding binding = new Binding();
    binding.Source = sliderFontSize;
    binding.Path = new PropertyPath("Value");
    binding.Mode = BindingMode.TwoWay;
    lblSimpleText.SetBinding(TextBlock.FontSizeProperty,binding);

    多绑定

    可以设置TextBlock元素从文本框中获取文本,从单独的颜色列表中选择当前前景色和背景色,等等。

    <TextBlock Grid.Row="1" Margin="10" Name="lblSimpleText"
       FontSize="{Binding ElementName=sliderFontSize,Path=Value}"
       Text="{Binding ElementName=txtContent,Path=Text}"
       Foreground="{Binding ElementName=lstColors,Path=SelectedItem.Tag}"> 
    </TextBlock>

    还可链接数据绑定。例如TextBox.Text属性创建表达式以链接到TextBlock.FontSize属性,而TextBlock.FontSize又链接到Slider.Value属性的绑定表达式。

    绑定更新

    源的变化会立即影响目标,然而反向的传递从目标到源未必会立即发生。他们的行为由Binding.UpdateSourceTrigger属性控制。

    名称

    说明

    PropertyChanged当目标属性变化时立即更新源。
    LostFocus当目标属性变化并且目标属性失去焦点时跟新源。
    Explicit除非调用BindingExpression.UpdateSource()方法,否则无法更新源。
    Default根据目标属性的元素确定更新行为。大多数属性的默认行为是PropertyChanged,但TextBox.Text属性的默认行为是LostFocus

    表中列出的值不影响目标的更新方式,他们仅控制OneWay或OneWayToSource模式的绑定中源的更新方式。

    绑定延迟

    用户停止输入500毫秒后更新源对象

    <TextBox Text="{Binding ElementName=txtSampleText,Path=FontSize,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,Delay=500}" Name="txtFontSize">
    </TextBox>

    绑定到非元素对象

    WPF数据绑定基础结构不能获取私有信息或公有字段,必须是公有属性中。

    绑定到非元素对象时,需要放弃Binding.ElementName属性,并使用以下属性之一。

    • Source:该属性是指向源对象的引用,提供数据的对象。
    • RelativeSource:这是引用,使用RelativeSource对象指向源对象。有了这个附加层,在在当前元素的基础上构建引用。这似乎增加了复杂程度,

    但实际上RelativeSource属性是一种特殊工具,当编写控件模版及数据模版时是很方便的。

    • DataContext:如果没有使用Source或RelativeSource属性指定源,WPF就从当前元素开始在元素树中向上查找。检查每个属性的DataContext属性,并使用第一个飞空的DataContext属性。

    当将同一个对象的多个属性绑定到不同的元素时,DataContext属性是非常有用的,因为可在更高层次的容器对象上,设置DataContext属性。

    Source

    绑定到静态对象

    <TextBlock Text="{Binding Source={x:Static SystemFonts.IconFontFamily},Path=Source}"></TextBlock>

    2.绑定到资源

    <Window.Resources>
     <FontFamily x:Key="CoustomFont">Calibri</FontFamily>
    </Window.Resources>
    <Grid>
     <TextBlock Text="{Binding Source={StaticResource CoustomFont},Path=Source}"></TextBlock>
    </Grid>

    RelativeSource

    <TextBlock Text="{Binding Path=Title,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}}}"></TextBlock>

    RelativeSource对象使用FindAncestor模式,该模式告知查找元素树知道发现AncestorType属性定义的元素类型。
    FindAncestor模式有4种。

    名称                 

    说明

    Self表达式绑定到同一元素的另一个属性上。
    FindAncestor表达式绑定到父元素。WPF将查找元素树直至发现期望的父元素。为了指定父元素,还必须设置AncestorType属性以指示希望查找的父元素类型。此外,还可以用AncestorLevel属性略过发现的一定的数量的特定元素。例如当一棵树中查找时,如果希望绑定到第三个ListBoxItem类型的元素,应当使用如下设置,AncestorType={x:Type ListBoxItem};并且AncestorLevel=3,从而略过前连个ListBoxItem元素。默认值是1,并在找到第一个匹配的元素停止查找。
    PreviousData表达式绑定到数据绑定列表中前一个数据项。在列表中使用这种模式。
    TemplateParent表达式绑定到应用模版的元素。只有当绑定位于控件模版或数据模版内部时,这种模式才能工作。

    DataContext属性

    大量元素绑定到同一对象。

    <TextBlock Text="{Binding Source={x:Static SystemFonts.IconFontFamily},Path=Source}"></TextBlock>
     <TextBlock Text="{Binding Source={x:Static SystemFonts.IconFontFamily},Path=Source}"></TextBlock>
     <TextBlock Text="{Binding Source={x:Static SystemFonts.IconFontFamily},Path=Source}"></TextBlock>
    

    可以改成如下

    <StackPanel DataContext="x:Static SystemFonts.IconFontFamily">
      <TextBlock Text="{Binding Path=Source}"></TextBlock>
      <TextBlock Text="{Binding Path=Source}"></TextBlock>
      <TextBlock Text="{Binding Path=Source}"></TextBlock>
     </StackPanel>

    具体例程讲解:

    第一个例子:

    第二个例子:

    先讲一下第一个例子:

        XMAL文件中的代码如下所示:

        <Grid Name="mygrid">
            <StackPanel>
                <TextBox Text="{Binding mytext}" Width="100" Margin="5"></TextBox>
                <TextBlock Text="{Binding mytext}" Margin="5,0,5,5" Width="100" Background="NavajoWhite"></TextBlock>
                <Button Width="100">click</Button>
            </StackPanel>
        </Grid>
    

    如上代码所示,TextBox控件的依赖项属性Text绑定到mytext,TextBlock的依赖项属性Text也是绑定到mytext (这就相当于告诉大家,同一个绑定源可以同时绑定到多个绑定目标), mytext是MainWindows中的一个自定义的myClass对象mcl的string类型的属性,其代码如下所示:
     

        public partial class MainWindow : Window
        {
            public myClass mcl { get; set; } = new myClass();
            public MainWindow()
            {
                InitializeComponent();
                mcl.mytext = "hello";
                mygrid.DataContext = mcl;//需要给mygrid控件指定DataContext为mcl,这是告诉Grid控件以及它子控件绑定源是谁
            }
        }
     
        public class myClass:INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            private string _mytext;
            public string mytext {
                get
                { return _mytext; }
                set
                {
                    _mytext = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("mytext"));
                }
            }
        }
    

    这个例子下,用户在TextBox框中输入字符串,只有当用户接着点击一下按钮或者将输入焦点改变到其他地方,TextBlox的字符串才会改变成和TextBox输入框的字符串一样。

        下面在进入第二个例子前,先讲一些有非常用的绑定知识:

        如上图所示,设置DataContext属性是为了告知绑定源对象,TextBox和TextBlock控件可以继承了来自Grid的绑定源。XMAL代码中的

    Text="{Binding mytext}"

    是告知两个控件绑定的路径,至此我们一定要牢记绑定的四大组成部分(一定要牢记):

    绑定源,这里例子是mcl;记住绑定源指的是对象;
    绑定路径,可以完全理解为绑定源的某个属性,在本例子里就是myClass类型的mytext属性。记住绑定路径指的是绑定源对象里的某个属性;
    绑定目标对象,这里例子是TextBox和TextBlock对象;
    绑定目标属性,这里的例子是TextBox和TextBlock对象的Text属性;记住目标属性一定是依赖项属性。
            根据微软官方文件,对于这个例子,需要了解的理论知识:

     (1)XMAL代码中出现的Binding扩展标记内的Path路径指定应当是指向一个对象的public 属性,Binding扩展标记中第一个参数可以省略Path:

    Text="{Binding mytext}"
    等价于:
    Text="{Binding Path=mytext}"

    (2)记住绑定目标属性一定是依赖项属性。这是第二遍强调了。绝大部分控件的属性都是依赖项属性。这也是告诉你如果你想自己实现一个自定义控件的属性,并且希望这个属性也可以像WPF官方控件一样绑定一个绑定源,那么你也要按照依赖项属性形式实现一个属性,关于依赖项属性的概念可以查看其它官网或百度资料,未来有空也会写一下这方面的知识,这里仅需要大家牢记的是绑定目标的属性必须是一个依赖项属性,不可辩驳!重要的事情说三遍。本篇文章看了能记住这一条你就比昨天进步了一点。
    (3)绑定流方向,绑定流方向是由Binding类对象的Mode属性设置的,它共有四种方向:
    OneWay,绑定源的属性值可以影响绑定目标属性的值;
    TwoWay,绑定源的属性值可以影响绑定目标属性的值,同样的绑定目标属性的值改变了也会影响绑定源属性的值;
    OneWayToSource,绑定目标属性的值改变可以影响绑定源属性的值;
    OneTime,绑定源属性的值在初始时绑定到绑定目标属性的值上,后面不再有任何影响。
    (4)但凡源想改变目标:也就是方向Mode属性是OneWay和TwoWay这两种类型来说,如果希望绑定源的每一次改变都能反映到绑定目标的属性值的改变上,那么您需要实现INotifyPropertyChanged接口。重新说一遍:如果你希望绑定源属性值(本例子为mytext属性)的更新能够自动反应到控件当中(也就是绑定源属性的值的改变能够同步改变到绑定目标属性的值),那么抱歉,WPF框架下,您必须得自己来实现INotifyPropertyChanged接口,这句话也是需要您牢记的,反正您只要按照这个接口实现了,您的属性值改变就可以自动影响界面的变化了,神奇的原因在于WPF框架内部都做好了。
    控件的每个依赖项属性都有默认的绑定方向,一一记住是不可能的,大致可以通过是否可编辑来大致判断属性值的绑定方向,如果是可编辑的那么相应的属性值是TwoWay方向,如果是不可编辑的一般来讲是OneWay。您也可以通过方法查询特定控件特定属性的默认绑定方向,这里不做详细说明。因此,该例子的TextBox的Text属性默认方向是TwoWay,而TextBlock的Text属性默认方向是OneWay。
    也就是目标反过来想改变源:也就是方向Mode属性是OneWayToSource或者TwoWay,这种情况下还涉及到Binding类型对象的UpdateSourceTrigger属性,它就是表示源影响目标的触发方式。UpdateSourceTrigger触发类型又分为三种:
    LostFocus,当控件失去焦点时改变源属性值;
    PropertyChanged,每当控件的属性值改变都立即改变源属性值;
    Explicit,用户自己通过调用UpdateSource方法来改变源属性的值,控制权在用户手上。
       该例子中,TextBox的UpdateSourceTrigger属性是默认是LostFocus,因此例子一当中不需要明确设置UpdateSourceTrigger值。

          至此我们就可以完全理解例子一的绑定效果了,它的过程时这样子的:

         TextBox和TextBlock都绑定到实现了INotifyPropertyChanged接口的myClass类的mytext属性上,由于TextBox绑定方向是TwoWay的,因此在TextBox输入框中改变值之后,然后点击按钮让TextBox输入框失去焦点,这个时候mytext值立即被改变,由于与TextBlock的绑定方向是OneWay,mytext值的改变立即影响了TextBlock,至此说明了整个绑定的基本细节。

        好,说了这么多,大家可以猜到如何在例子一上做改动实现例子二了吧。很好,有些同学可能猜到了,只需要改XMAL中的一处即可:

        <Grid Name="mygrid">
            <StackPanel>
                <TextBox Text="{Binding mytext,UpdateSourceTrigger=PropertyChanged}" Width="100" Margin="5"></TextBox>
                <TextBlock Text="{Binding mytext}" Margin="5,0,5,5" Width="100" Background="NavajoWhite"></TextBlock>
                <Button Width="100">click</Button>
            </StackPanel>
        </Grid>
    

    如上所示,在TextBox的Text属性的Binding扩展标记中添加UpdateSourceTrigger=PropertyChanged即可,这个时候只要用户在TextBox的输入框中改变内容就会立即反应到TextBlock当中。

    展开全文
  • Java的动态绑定和静态绑定

    千次阅读 多人点赞 2017-09-14 17:05:16
    这就涉及到程序绑定这个概念。程序绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对Java来说,绑定分为静态绑定和动态绑定;或者叫做前期绑定和后期绑定。静态绑定在程序执行前方法已经被绑定,此时由...

    引言

    在Java方法调用的过程中,JVM是如何知道调用的是哪个类的方法源代码呢?这就涉及到程序绑定这个概念。

    程序绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对Java来说,绑定分为静态绑定动态绑定;或者叫做前期绑定和后期绑定。

    静态绑定

    在程序执行前方法已经被绑定,此时由编译器或其它连接程序实现。例如:C。

    针对Java,可以简单地理解为程序编译期的绑定。这里特别说明一点,Java当中的方法只有finalstaticprivate构造方法是静态绑定。

    请看如下Java代码:

    //被调用的类
    package hr.test;
    class Father{
          public static void f1(){
                  System.out.println("Father— f1()");
          }
    }
    //调用静态方法
    import hr.test.Father;
    public class StaticCall{
           public static void main(){
                Father.f1(); //调用静态方法
           }
    }

    上面的源代码中执行方法调用的语句Father.f1()被编译器编译成了一条指令:invokestatic #13

    我们看看JVM是如何处理这条指令的:

    (1) 指令中的#13指的是StaticCall类的常量池中第13个常量表的索引项(关于常量池详见《Class文件内容及常量池 》)。这个常量表(CONSTANT_Methodref_info ) 记录的是方法f1信息的符号引用(包括f1所在的类名,方法名和返回类型)。JVM会首先根据这个符号引用找到方法f1所在的类的全限定名: hr.test.Father

    (2) 紧接着JVM会加载、链接和初始化Father类。

    (3) 然后在Father类所在的方法区中找到f1()方法的直接地址,并将这个直接地址记录到StaticCall类的常量池索引为13的常量表中。这个过程叫常量池解析 ,以后再次调用Father.f1()时,将直接找到f1方法的字节码

    (4) 完成了StaticCall类常量池索引项13的常量表的解析之后,JVM就可以调用f1()方法,并开始解释执行f1()方法中的指令了。

    通过上面的过程,我们发现经过常量池解析之后,JVM就能够确定要调用的f1()方法具体在内存的什么位置上了。实际上,这个信息在编译阶段就已经在StaticCall类的常量池中记录了下来。这种在编译阶段就能够确定调用哪个方法的方式,我们叫做静态绑定机制 。

    除了被static修饰的静态方法,所有被private修饰的私有方法、被final 修饰的禁止子类覆盖的方法都会被编译成invokestatic指令。另外所有类的初始化方法< init >和< clinit >会被编译成invokespecial指令。JVM会采用静态绑定机制来顺利的调用这些方法。

    动态绑定

    在运行时根据具体对象的类型进行绑定。

    若一种语言实现了后期绑定,同时必须提供一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:它们都要在对象中安插某些特殊类型的信息。

    看如下Java代码:

    package hr.test;
    //被调用的父类
    class Father{
        public void f1(){
            System.out.println("father-f1()");
        }
            public void f1(int i){
                    System.out.println("father-f1()  para-int "+i);
            }
    }
    //被调用的子类
    class Son extends Father{
        public void f1(){ //覆盖父类的方法
            System.out.println("Son-f1()");
        }
            public void f1(char c){
                    System.out.println("Son-s1() para-char "+c);
            }
    }
    
    //调用方法
    import hr.test.*;
    public class AutoCall{
        public static void main(String[] args){
            Father father=new Son(); //多态
            father.f1(); //打印结果: Son-f1()
        }
    }

    上面的源代码中有三个重要的概念:多态(polymorphism) 、方法覆盖方法重载
    打印的结果大家也都比较清楚,但是JVM是如何知道f.f1()调用的是子类Sun中方法而不是Father中的方法呢?在解释这个问题之前,我们首先简单的讲下JVM管理的一个非常重要的数据结构——方法表

    在JVM加载类的同时,会在方法区中为这个类存放很多信息(详见《Java 虚拟机体系结构 》)。其中就有一个数据结构叫方法表它以数组的形式记录了当前类及其所有超类的可见方法字节码在内存中的直接地址

    下图是上面源代码中Father和Sun类在方法区中的方法表:
    这里写图片描述

    可以看出方法表有两个特点:

    • 子类方法表中继承了父类的方法,比如Father extends Object。
    • 相同的方法(相同的方法签名:方法名和参数列表)在所有类的方法表中的索引相同。比如Father方法表中的f1()和Son方法表中的f1()都位于各自方法表的第11项中。

    对于上面的源代码,编译器首先会把main方法编译成下面的字节码指令

    0  new hr.test.Son [13] //在堆中开辟一个Son对象的内存空间,并将对象引用压入操作数栈
    3  dup  
    4  invokespecial #7 [15] // 调用初始化方法来初始化堆中的Son对象 
    7  astore_1 //弹出操作数栈的Son对象引用压入局部变量1中
    8  aload_1 //取出局部变量1中的对象引用压入操作数栈
    9  invokevirtual #15 //调用f1()方法
    12  return

    其中invokevirtual指令的详细调用过程是这样的:

    (1) invokevirtual指令中的#15指的是AutoCall类的常量池中第15个常量表的索引项。这个常量表(CONSTANT_Methodref_info ) 记录的是方法f1信息的符号引用(包括f1所在的类名,方法名和返回类型)。JVM会首先根据这个符号引用找到调用方法f1的类的全限定名: hr.test.Father。这是因为调用方法f1的类的对象father声明为Father类型。

    (2) 在Father类型的方法表中查找方法f1,如果找到,则将方法f1在方法表中的索引项11(如上图)记录到AutoCall类的常量池中第15个常量表中(常量池解析 )。

    这里有一点要注意:如果Father类型方法表中没有方法f1,那么即使Son类型中方法表有,编译的时候也通过不了。因为调用方法f1的类的对象father的声明为Father类型。

    (3) 在调用invokevirtual指令前有一个aload_1指令,它会将开始创建在堆中的Son对象的引用压入操作数栈。然后invokevirtual指令会根据这个Son对象的引用首先找到堆中的Son对象,然后进一步找到Son对象所属类型的方法表。过程如下图所示:
    这里写图片描述

    (4)这是通过第(2)步中解析完成的#15常量表中的方法表的索引项11,可以定位到Son类型方法表中的方法f1(),然后通过直接地址找到该方法字节码所在的内存空间。

    很明显,根据对象(father)的声明类型(Father)还不能够确定调用方法f1的位置,必须根据father在堆中实际创建的对象类型Son来确定f1方法所在的位置。这种在程序运行过程中,通过动态创建的对象的方法表来定位方法的方式,我们叫做动态绑定机制 。

    合适的方法

    上面的过程很清楚的反映出在方法覆盖的多态调用的情况下,JVM是如何定位到准确的方法的。但是下面的调用方法JVM是如何定位的呢?(仍然使用上面代码中的Father和Son类型)

    public class AutoCall{
           public static void main(String[] args){
                 Father father=new Son();
                 char c='a';
                 father.f1(c); //打印结果:father-f1()  para-int 97
           }
    }

    问题是Fahter类型中并没有方法签名为f1(char)的方法呀。但打印结果显示JVM调用了Father类型中的f1(int)方法,并没有调用到Son类型中的f1(char)方法。

    根据上面详细阐述的调用过程,首先可以明确的是:JVM首先是根据对象father声明的类型Father来解析常量池的(也就是用Father方法表中的索引项来代替常量池中的符号引用)。如果Father中没有匹配到”合适” 的方法,就无法进行常量池解析,这在编译阶段就通过不了

    那么什么叫”合适”的方法呢?当然,方法签名完全一样的方法自然是合适的。但是如果方法中的参数类型在声明的类型中并不能找到呢?比如上面的代码中调用father.f1(char),Father类型并没有f1(char)的方法签名。实际上,JVM会找到一种“凑合”的办法,就是通过 参数的自动转型 来找 到“合适”的 方法。比如char可以通过自动转型成int,那么Father类中就可以匹配到这个方法了 (关于Java的自动转型问题可以参见《【解惑】Java类型间的转型》)。但是还有一个问题,如果通过自动转型发现可以“凑合”出两个方法的话怎么办?比如下面的代码:

    class Father{
        public void f1(Object o){
            System.out.println("Object");
        }
        public void f1(double[] d){
            System.out.println("double[]");
        }
    
    }
    public class Demo{
        public static void main(String[] args) {
            new Father().f1(null); //打印结果: double[]
        }
    }

    null可以引用于任何的引用类型,那么JVM如何确定“合适”的方法呢。一个很重要的标准就是:如果一个方法可以接受传递给另一个方法的任何参数,那么第一个方法就相对不合适。比如上面的代码: 任何传递给f1(double[])方法的参数都可以传递给f1(Object)方法,而反之却不行,那么f1(double[])方法就更合适。因此JVM就会调用这个更合适的方法。

    属性是动态绑定的吗

    首先来看代码:

    public class Father {   
    
      protected String name="父亲属性";   
         
      public void method() {   
        System.out.println("父类方法,对象类型:" + this.getClass());   
      }   
    }   
         
    public class Son extends Father {   
      protected String name="儿子属性";   
         
      public void method() {   
        System.out.println("子类方法,对象类型:" + this.getClass());   
      }   
         
      public static void main(String[] args) {   
        Father sample = new Son();//向上转型   
        System.out.println("调用的成员:"+sample.name);   
      }   
    }

    运行结果:

    调用的成员为父亲的属性

    这个结果表明,子类的对象(由父类的引用handle)调用到的是父类的成员变量。所以必须明确,运行时(动态)绑定针对的范畴只是对象的方法。

    现在试图调用子类的成员变量name,该怎么做?最简单的办法是将该成员变量封装成方法getter形式:

    public class Father {   
      protected String name = "父亲属性";   
      public String getName() {   
        return name;   
      }   
      public void method() {   
        System.out.println("父类方法,对象类型:" + this.getClass());   
      }   
    }   
         
    public class Son extends Father {   
      protected String name="儿子属性";   
         
      public String getName() {   
        return name;   
      }   
         
      public void method() {   
        System.out.println("子类方法,对象类型:" + this.getClass());   
      }   
         
      public static void main(String[] args) {   
        Father sample = new Son();//向上转型   
        System.out.println("调用的成员:"+sample.getName());   
      }   
    }

    常见面试问题

    重写和重载的区别

    重写(override)

    Java的method overriding则发生在虚方法之间。调用虚方法时,Java采用的是延迟绑定 / 动态分派的语义,根据被调用对象(receiver)的实际类型来决定选择哪个版本的虚方法。

    一个实例方法可以重写(override)在其超类中可访问到的具有相同签名的所有实例方法,从而使能了动态分派(dynamic dispatch);换句话说,JVM将基于实例的运行期类型来选择要调用的重写方法。重写是面向对象编程技术的基础,并且是唯一没有被普遍劝阻的名字重用形式:

    class Base{
          public void f(){}
    }
    class Derived extends Base{
          public void f(){}
    }

    重写的特点

      1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果

      2、覆盖的方法的返回值必须和被覆盖的方法的返回一致;

      3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;

      4、被覆盖的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。

    重载(overload)

    在某个类中的方法可以重载(overload)另一个方法,只要它们具有相同的名字和不同的签名。由调用所指定的重载方法是在编译期选定的:

    class CircuitBreaker{
          public void f (int i){}    //int overloading
          public void f(String s){}   //String overloading
    }

    有一个值得注意的地方:

    • 所谓的重载是静态绑定的也只是指在编译期f (int i)f(String s)方法签名不同,运行期我们知道调用的是f (int i)还是f(String s)。但是调用的是哪个类的方法还要根据实例对象去判断。

    例如如下代码:

    public class Test {
        public static void main(String[] args) {
            Animal animal = new Animal();
            animal.eat();
            animal.eat(1);
            animal.eat("1");
        }
    }
    
    class Animal {
        public void eat() {
    
        }
    
        public void eat(int a) {
    
        }
    
        public void eat(String a) {
    
        }
    }

    对应的字节码:

    public class com.example.tsnt.Test {
      public com.example.tsnt.Test();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: new           #2                  // class com/example/tsnt/Animal
           3: dup
           4: invokespecial #3                  // Method com/example/tsnt/Animal."<init>":()V
           7: astore_1
           8: aload_1
           9: invokevirtual #4                  // Method com/example/tsnt/Animal.eat:()V
          12: aload_1
          13: iconst_1
          14: invokevirtual #5                  // Method com/example/tsnt/Animal.eat:(I)V
          17: aload_1
          18: ldc           #6                  // String 1
          20: invokevirtual #7                  // Method com/example/tsnt/Animal.eat:(Ljava/lang/String;)V
          23: return
    }

    可以看到其中这几行:

           9: invokevirtual #4                  // Method com/example/tsnt/Animal.eat:()V
          14: invokevirtual #5                  // Method com/example/tsnt/Animal.eat:(I)V
          20: invokevirtual #7                  // Method com/example/tsnt/Animal.eat:(Ljava/lang/String;)V

    对于调用哪个重载的方法,编译阶段已经确定下来了,但是对于调用哪个类的方法编译阶段没有确定下来,所以显示的是invokevirtual,这个要等到运行时才能确定。

    重载的特点

      1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是fun(int, float), 但是不能为fun(int, int))

      2、不能通过访问权限、返回类型、抛出的异常进行重载;

      3、方法的异常类型和数目不会对重载造成影响;

      4、对于继承来说,如果某一方法在父类中是访问权限是priavte,那么就不能在子类对其进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。

    静态属性和静态方法能否被继承,能否重写

    静态方法和属性是属于类的,调用的时候直接通过类名.方法名完成的,不需继承机制就可以调用如果子类里面定义了和父类声明一样的静态方法和属性,那么这时候父类的静态方法或属性称之为“隐藏”,你如果想要调用父类的静态方法和属性,直接通过父类名.方法名或变量名完成,至于是否继承一说,子类是有继承静态方法和属性,但是跟实例方法和属性不太一样,存在“隐藏”的这种情况。

    多态之所以能够实现是依赖于继承和重写 、重载(继承和重写最为关键)。有了继承和重写就可以 实现父类的引用可以指向不同子类的对象。重写的功能是:“重写”后子类的优先级要高于父类的优先级,但是“隐藏”是没有这个优先级之分的。

    结论:静态属性、静态方法和非静态的属性都可以被继承和隐藏而不能够被重写,因此不能实现多态,不能实现父类的引用可以指向不同子类的对象。非静态的方法可以被继承和重写,因此可以实现多态。

    附:
    查看字节码的方法:查看Java字节码的方法

    参考:
    1.java中静态属性和和静态方法的继承问题 以及多态的实质
    2.java的动态绑定与静态绑定
    3.【解惑】Java动态绑定机制的内幕
    4.Java的函数重载为什么采取静态静态绑定而非动态绑定?

    展开全文
  • 绑定到简单属性: 绑定到集合:' runat="server"> 绑定到表达式: 绑定到方法返回值: 绑定到Hashtable: 绑定到ArrayList: 若数组里里放的是对象则可能要进行必要的转换后再绑定如: 绑定到DataView,DataTable,...

    本文来自网络,来源也是转载,谁有源地址,我加链接进来

    灵活的运用数据绑定操作

    绑定到简单属性:<%#UserName%>
    绑定到集合:<asp:ListBox id="ListBox1" datasource='<%# myArray%>' runat="server">
    绑定到表达式:<%#(class1.property1.ToString() + "," + class1.property2.ToString())%>
    绑定到方法返回值:<%# GetSafestring(str) %>
    绑定到Hashtable:<%# ((DictionaryEntry)Container.DataItem).Key%>
    绑定到ArrayList:<%#Container.DataItem %>
    若数组里里放的是对象则可能要进行必要的转换后再绑定如:
    <%#((对象类型)Container.DataItem).属性%>
    绑定到DataView,DataTable,DataSet:
    <%#((DataRowView)Container.DataItem)["字段名"]%>或
    <%#((DataRowView)Container.DataItem).Rows[0]["字段名"]%>
    要格式化则:
    <%#string.Format("格式",((DataRowView)Container.DataItem)["字段名"])%>
    <%#DataBinder.Eval(Container.DataItem,"字段名","格式")%>
    绑定到DataReader:
    <%#((IDataReader)Container.DataItem).字段名%>
    当然为了方便一般使用最多的就是DataBinder类的Eval方法了.不过这样对于同时要绑定大量的数据效率要低一些
    在绑定数据时经常会用到这个句程序:<%# DataBinder.Eval(Container.DataItem,"xxxx")%>或者<%# DataBinder.Eval(Container,"DataItem.xxxx")%> 
    今天又学到一种,而且微软也说这种方法的效率要比以上两种高。
    <%# ((DataRowView)Container.DataItem)["xxxx"]%>
    很有用的,这样可以在前台页面做好多事情了。
    还要记住要这样用必须要在前台页面导入名称空间System.Data,否则会生成错误信息。
    <%@ Import namespace="System.Data" %>
    这种用法其实和<%# ((DictionaryEntry)Container.DataItem).Key%>是一个道理。
    绑定到DataSet、DataTable时:
    <%#((System.Data.DataRowView)Container.DataItem)["字段名"]%>
    <%#((System.Data.DataRowView)Container.DataItem)[索引]%>


    绑定到DataReader时:
    <%#((System.Data.Common.DbDataRecord)Container.DataItem)[索引]%>
    <%#((System.Data.Common.DbDataRecord)Container.DataItem)["字段名"]%>
    关键是Container这个东西,它比较神秘。它的名称空间是System.ComponentModel。对于它我还需要进一步理解。  
    初学.NET,现在在看DataGrid控件,在ItemTemplate显示数据时,
    DataBinder.Eval(Container.DataItem,"Name")和Container.DataItem("Name")有什么区别?


    DataBinder是System.Web里面的一个静态类,它提供了Eval方法用于简化数据绑定表达式的编写,但是它使用的方式是通过Reflection等开销比较大的方法来达到易用性,因此其性能并不是最好的。而Container则根本不是任何一个静态的对象或方法,它是ASP.NET页面编译器在数据绑定事件处理程序内部声明的局部变量,其类型是可以进行数据绑定的控件的数据容器类型(如在Repeater内部的数据绑定容器叫RepeaterItem),在这些容器类中基本都有DataItem属性,因此你可以写Container.DataItem,这个属性返回的是你正在被绑定的数据源中的那个数据项。如果你的数据源是DataTable,则这个数据项的类型实际是DataRowView。
    展开全文
  • 绑定绑定

    千次阅读 2011-04-21 10:38:00
    1、 概念 首先,什么是绑定?( what`s the definition of binding? ) c++编程思想上有说到: Connecting a function call to a function body is called binding.(将函数体和函数调用关联...
  • //链接的时候把drink指令上的flavor属性放在scope,然后在template显示 } } }); 这时候的DOM结构如下: 但是,这种方式要通过attrs.flavor来获取这个指令的属性值,然后需要把这个属性绑定到scope...
  • java深入理解动态绑定

    千次阅读 2017-02-26 15:38:16
    在面向对象的程序设计语言,多态是继数据抽象和继承之后的第三种基本特性。多态通过分离做什么和怎么做,从另一个角度将接口和实现分离开来。...绑定概念通常,我们将一个方法调用同一个方法主体关联起来称作绑定
  • 绑定绑定,迟早都要绑定

    千次阅读 2010-05-02 13:47:00
    1、 概念首先,什么是绑定?( what`s the definition of binding? )c++编程思想上有说到:Connecting a function call to a function body is called binding.(将函数体和函数调用关联起来,就叫绑定)然后,那么...
  • 1. Binding的Path表示该控件绑定到的类的哪个属性是该控件需要关心的。 2. Binding的ElementName属性或RleativeSource属性指定绑定源。 ////////////////////////////////////////////// 前置声明:代码...
  • 之所以出现此问题,是因为网卡绑定属性没有传播到 ESXi 的管理网络端口组。我们从端口组的负载平衡策略下拉菜单,可以指定虚拟交换机如何对组内物理网卡之间的出站通信进行负载平衡。它一般有以下几种方式:1、...
  • DOM将文档看作一颗树,其中的每个成分都是对象,这些对象都看作是节点。可以将文档的一切都理解成节点...Object(对象):DOM的每个节点都是对象,通过对象的属性和方法就能够操作节点。 Model(模型):DOM将整个文档
  • 函数的this的四种绑定形式

    千次阅读 2017-11-09 14:29:17
    一谈到this,很多让人晕晕乎乎的抽象概念就跑出来了,这里我就只说最核心的一点——函数的this总指向调用它的对象,接下来的故事都将围绕这一点展开 (提醒前排的筒子们准备好茶水和西瓜,我要开始讲故事啦!!...
  • Android官方数据绑定框架DataBinding

    万次阅读 多人点赞 2015-08-31 14:29:59
    今天来了解一下android最新给我们带来的数据绑定...数据绑定框架给我们带来了更大的方便性,以前我们可能需要在Activity里写很多的findViewById,烦人的代码也增加了我们代码的耦合性,现在我们马上就可以抛弃那么
  • 学习WPF绑定

    千次阅读 2013-11-22 09:03:55
    数据绑定是指从一个对象提取信息,并在应用程序的用户界面...因为许多Windows应用程序都会用到数据(并且所有这些应用程序在某些时候需要处理数据),所以在用户界面技术数据绑定和WPF一样,也是一个非常重要的概念
  • 我们在学习JavaScript,难免都会去网上查一些资料。也许偶尔就会遇到“事件委托”(也有的称我“事件代理”,这里不评论谁是谁非。以下全部称为“事件委托”),尤其是在查JavaScript的事件处理的时候。但是,...
  • ASP.NET数据绑定总结

    千次阅读 2013-03-21 18:09:54
    概念: 数据绑定(data binding):数据源与...ASP.NET涉及到的数据绑定大概可以分为: 使用 使用DataSource属性 使用数据源控件 使用Eval方法   使用 绑定数据源
  • asp.net 前后台之间数据的绑定

    千次阅读 2016-04-22 09:04:48
    经常会碰到在前台代码要使用(或绑定)后台代码变量值的问题。一般有和两种方式,这里简单总结一下。如有错误或异议之处,敬请各位指教。  一方面,这里所讲的前台即通常的.aspx文件,后台指的是与aspx相关联的...
  • JVM的堆里面存放对象,每个对象就是通过一个类来生成的嘛,此时对象本身是没有信息的,只能通过绑定一个类来获得信息,也就是获得类的属性,那对象和类是怎么绑定信息的呢,也就是怎么确定他们的一对一关系呢?...
  • 文件系统与文件属性

    千次阅读 2016-05-27 14:52:50
    系统编程概念与文件属性 本文是作者阅读TLPI(The Linux Programer Interface的总结),为了突出重点,避免一刀砍,我不会过多的去介绍基本的概念和用法,我重点会去介绍原理和细节。因此对于本文的读者,至少要求读过...
  • Vue3.0新特性之Proxy实现双向绑定

    千次阅读 2020-08-20 10:13:30
    双向绑定这个概念应该已经不是个陌生的概念了,只要提到MVVM那就不得不提到它,我们来看Vue的三要素: 响应式: Vue如何监听到data的每个属性变化 模板引擎: Vue的模板如何被解析,指令如何处理 渲染: Vue如何将...
  • 经常会碰到在前台代码要使用(或绑定)后台代码变量值的问题。一般有和两种方式,这里简单总结一下。如有错误或异议之处,敬请各位指教。  一方面,这里所讲的前台即通常的.aspx文件,后台指的是与aspx相...
  • 在桌面应用程序实现 Beans 和数据绑定 <!--google_ad_client = "pub-2332279788637932";//300x250, 创建于 07-12-5google_ad_slot = "9916274731";google_ad_width = 300;google_ad_height = 250;//-->
  • C++的动态类型与动态绑定、虚函数、运行时多态的实现,认真捉摸。
  • 信号槽是Qt特有的概念。它使得程序员将不同的object绑定起来,而object对象间并不需要对相互了解。 Slots也是普通的c++方法,它们可以是virtual;可以被重载;可以使private、protected、public,可以像其它c++方法...
  • pomelo的基本概念

    千次阅读 2015-04-13 17:31:52
    动态语言的面向对象有个基本概念叫鸭子类型。 服务器的抽象也同样可以比喻为鸭子, 服务器的对外接口只有两类, 一类是接收客户端的请求, 叫做handler, 一类是接收RPC请求, 叫做remote, handler和remote的...
  • WPF数据绑定详解

    千次阅读 2013-09-10 10:54:56
    Windows Presentation Foundation (WPF) 数据绑定为应用程序提供了一种简单而一致的方法来显示数据以及与数据交互。元素可以以公共语言运行库 (CLR) 对象和 XML 的形式绑定到各种数据源的数据。ContentControl(如 ...
  • 程序的静态链接,动态链接和装载

    千次阅读 2017-04-14 09:59:07
    转自:程序的静态链接,动态链接和装载 ...一、程序编译链接的整体流程 ...二、目标文件的样子...静态链接是在生成可执行程序的时候就把库的内容加入到程序。 载入时动态链接是在将功能模块读入内存时把动态
  • Python如何获取类属性的列表

    千次阅读 2018-01-16 10:42:00
    这篇文章主要给大家介绍了在Python如何获取类属性的列表,文中通过示例代码介绍的很详细,相信对大家的学习或者工作具有一定的参考借鉴价值,有需要的朋友可以参考借鉴,下面来一起看看吧。 前言 最近工作遇到...
  • 理解VUE双向数据绑定原理和实现

    千次阅读 多人点赞 2021-02-26 12:04:02
    原文链接:https://www.jianshu.com/p/e7ebb1500613 一、原理: 1.vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随...
  • 多维建模和MDX出现的一些概念

    千次阅读 2012-10-10 16:16:30
    Microsoft SQL Server Analysis Services 多维数据集是基于度量值...“(全部)”成员是属性层次结构或用户定义的层次结构的所有成员的计算值。 属性层次结构 “属性层次结构”是包含以下级别的属性成员层次结构:

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 58,191
精华内容 23,276
关键字:

绑定中的属性链接概念