JAVA初学问题

作者&投稿:戚须 (若有异议请与网页底部的电邮联系)
java 初学问题~

''是字符,""是字符串
''之间加空格,' '

我先必须指明,楼上的回答都是错误的或者不明确的,当你把String换成一个不可拆箱的对象时,就是指向地址,而不是值了,至于JAVA基础数据类型到底是不是真正的值类型,
这个问题对于很多java初学者来说都存疑过,我觉得解答的最好的是王垠的一篇文章。
我先贴出原文地址:网页链接
Java 有值类型,原始类型 int,boolean 等是值类型,其实是长久以来的一种误解,它混淆了实现和语义的区别。不要以为 Java 的官方文档那样写就是权威定论,就可以说“王垠不懂” :) 当你认为王垠不懂一个初级问题的时候,都需要三思,因为他可能是大智若愚…… 看了我下面的论述,也许你会发现自己应该怀疑的是,Java 的设计者到底有没有搞明白这个问题 :P
胡扯结束,现在来说正事。Java,Scheme 等语言的原始类型,比如 char,int,boolean,double 等,在“实现”上确实是通过值(而不是引用,或者叫指针)直接传递的,然而这完全是一种为了效率的优化(叫做 inlining)。这种优化对于程序员应该是不可见的。Java 继承了 Scheme/Lisp 的衣钵,它们在“语义”上其实是没有值类型的。
这不是天方夜谭,为了理解这一点,你可以做一个很有意思的思维实验。现在你把 Java 里面所有的原始类型都“想象”成引用类型,也就是说,所有的 int, boolean 等原始类型的变量都不包含实际的数据,而是引用(或者叫指针),指向堆上分配的数据。然后你会发现这样“改造后”的 Java,仍然符合现有 Java 代码里能看到的一切现象。也就是说,原始类型被作为值类型还是引用类型,对于程序员完全没有区别。
举个简单的例子,如果我们把 int 的实现变成完全的引用,然后来看这段代码:
int x = 1; // x指向内存地址A,内容是整数1int y = x; // y指向同样的内存地址A,内容是整数1x = 2; // x指向另一个内存地址B,内容是整数2。y仍然指向地址A,内容是1。
由于我们改造后的 Java 里面 int 全部是引用,所以第一行定义的 x 并不包含一个整数,而是一个引用,它指向堆里分配的一块内存,这个空间的内容是整数 1。在第二行,我们定 int 变量 y,当然它也是一个引用,它的值跟 x 一样,所以 y 也指向同一个地址,里面的内容是同一个整数:1。在第三行,我们对 x 这个引用赋值。你会发现一个很有意思的现象,虽然 x 指向了 2,y 却仍然指向 1。对 x 赋值并没能改变 y 指向的内容,这种情况就跟 int 是值类型的时候一模一样!所以现在虽然 int 变量全部是引用,你却不能实现共享地址的引用能做的事情:对 x 进行某种操作,导致 y 指向的内容也发生改变。
出现这个现象的原因是,虽然现在 int 成了引用类型,你却并不能对它进行引用类型所特有(而值类型没有)的操作。这样的操作包括:
deref。就像 C 语言里的 * 操作符。
成员赋值。就像对 C struct 成员的 x.foo = 2 。
在 Java 里,你没法写像 C 语言的 *x = 2 这样的代码,因为 Java 没有提供 deref 操作符 *。你也没法通过 x.foo = 2 这样的语句改变 x 所指向的内存数据(内容是1)的一部分,因为 int 是一个原始类型。最后你发现,你只能写 x = 2,也就是改变 x 这个引用本身的指向。x = 2 执行之后,原来数字 1 所在的内存空间并没有变成 2,只不过 x 指向了新的地址,那里装着数字 2 而已。指向 1 的其它引用变量比如 y,不会因为你进行了 x = 2 这个操作而看到 2,它们仍然看到原来那个1……
在这种 int 是引用的 Java 里,你对 int 变量 x 能做的事情只有两种:
读出它的值。
对它进行赋值,使它指向另一个地方。
这两种事情,就跟你能对值类型能做的两件事情没有区别。这就是为什么你没法通过对 x 的操作而改变 y 表示的值。所以不管 int 在实现上是传递值还是传递引用,它们在语义上都是等价的。也就是说,原始类型是值类型还是引用类型,对于程序员来说完全没有区别。你完全可以把 Java 所有的原始类型都想成引用类型,之后你能对它们做的事情,你的编程思路和方式,都不会因此有任何的改变。
从这个角度来看,Java 在语义上是没有值类型的。值类型和引用类型如果同时并存,程序员必须能够在语义上感觉到它们的不同,然而不管原始类型是值类型还是引用类型,作为程序员,你无法感觉到任何的不同。所以你完全可以认为 Java 只有引用类型,把原始类型全都当成引用类型来用,虽然它们确实是用值实现的。
一个在语义上有值类型的语言(比如 C#,Go 和 Swift)必须具有以下两种特性之一(或者两者都有),程序员才能感觉到值类型的存在:
deref 操作。这使得你可以用 *x = 2 这样的语句来改变引用指向的内容,导致共享地址的其它引用看到新的值。你没法通过 x = 2 让其他值变量得到新的值,所以你感觉到值类型的存在。
像 struct 这样的“值组合类型”。你可以通过 x.foo = 2 这样的成员赋值改变引用数据(比如 class object)的一部分,使得共享地址的其它引用看到新的值。你没法通过成员赋值让另一个 struct 变量得到新的值,所以你感觉到值类型的存在。
实际上,所有的数据都是引用类型就是 Scheme 和 Java 最初的设计原理。原始类型用值来传递数据只是一种性能优化(叫做 inlining),它对于程序员应该是透明(看不见)的。那些在面试时喜欢问“Java 是否所有数据都是引用”,然后当你回答“是”的时候纠正你说“int,boolean 是值类型”的人,都是本本主义者。

先说一下面向过程和面向对象,这是两种思想,它们都能达到用程序来完成一件事情的能力。
只不过思维方式不一样而已。

面向过程是把一件事一项工程分解成为一个个小的功能,用一个个函数来实现.
面向对象是把事情看成是一个个小的对象组成的,或者说一个个小部分组成的,这些对象之间的相互关系,构成了整个项目.

在面向对象的思想中,万物皆对象,我是,你是,他也是。
而"类",就是对象的抽象或者说是概括。比如,我你他都可以概括为人类。
总的来说,类是抽象的虚的,而对象是一个个活生生的具体的事物。
人是一个类,我你他就是对象。

一般的面向对象程序设计方法都是先设计一个类,然后由这个类产生一个对象。
之后是对这个对象进行相关操作。
要说明一点:操作是对对象进行的,没有对象就无所谓操作。

下面说说如何设计一个类,
类是有一些属性和功能封装起来的。

在面向过程的思想里,一个程序一般都是由一个个函数组成的,这些函数之间相互调用,
就形成了一个完整的程序,解决了一个问题。它的基本结构是:

函数一()
{
……;
}

函数二()
{
……;
}

……

主函数()
{
……;
}

但是在面向对象的思想中,是把这些都封装起来,形成一个类。

class 类名
{
函数一()
{
……;
}

函数二()
{
……;
}

……
}

然后由这个类产生一个对象,比如:我们把一个类的类名起为 student
那么产生对象的方法就是: student s1;
这里s1是一个对象,产生了这个对象以后,才可以进行相关操作。
操作方法如: s1.函数一();
等等。具体的细节在此就不说了,此文只说思想。

说得再明白一点就是,把具体的实现过程放在类里面,之后产生一个对象,有对象调用相关操作。
犹如把面向过程里的函数都封装进了类里,然后再由对象来操作。

一个类主要就是封装,一般把它当成一个模块,在需要的时候可以让其他类调用。
类是一个抽象,一个概括,把一些有共同特征的东西抽象化,提出它们的公共部分,封装在一起。
关于封装,上文已经说过,就是把一些属性和功能装在一个容器里面。
下面我用一个游戏来解说一下:

假设我们要做一个小游戏,类似于网游里面的打怪,为简单起见,认为怪不打人,只让人打,
他的血不断减少,直到死亡。

把所有怪物的共同特征抽象出来,于是我们得到一个类:怪物
class 怪物
{
char 怪物名;
int 血;

怪物(怪物名n,血n) /*构造函数*/
{
怪物名=怪物名n;
血=血n;
}

被打函数()
{
血减少;
}

判断函数()
{
if (血==0)
printf("你胜利了!");
}

玩游戏()
{
while (血 > 0)
{
被打函数();
判断函数();
}
}
}

这样,就定义了一个怪物类,他有属性:怪物名、血,有功能:构造、被打、判断
根据这个,就可以产生对象了。

一个类可以产生任意多的对象,这些对象根据构造函数的不同来区别。

我们先继续来写我们的程序
main主函数
void main()
{
/******产生对象******/
怪物 怪物1("狼",5000);
怪物 怪物2("虎",8000);
怪物 怪物3("蛇",3000);

/**有了几个对象以后才能开始我们的游戏**/
怪物1.玩游戏();
怪物2.玩游戏();
怪物3.玩游戏();
}

再这个主函数中,我们建立了三个对象,它们共用一个类。
可以看到,类相当于一个组件,一个模块,我们在需要的时候只要建立它的对象,就能实现他所封装的功
能。
这就是面向对象的优点,可以重用,不必每一次用到时都重写。

说了这么多,自己感觉还是没说明白,真有点只可意味不可言传的感觉。
其实要是书看的多了,真正认真地写上几个东西,就能够理解了,无形之中就会有感觉的。


class Vol{
private float a;
private float b;
private float c;
private float r;
private float h;
private float d;
public void setA(float x){a=x;}
public void setB(float y){b=y;}
public void setC(float z){c=z;}
public void setD(float m){d=m;}
public void setR(float x){r=x;}
public void setH(float y){h=y;}
public float getA(){return a;}
public float getB(){return b;}
public float getC(){return c;}
public float getD(){return d;}
public float getR(){return r;}
public float getH(){return h;}
public double getArea(){
return Math.PI*r*r;
}
public float volume(float a){
return a*a*a;
}
public float volume(float b,float c,float d){
return b*c*d;
}
public double volume(float r,float h){
return Math.PI*r*r*h;
}
}

public class exp06 {

public static void main(String[] args) {
Vol v1=new Vol();
Vol v2=new Vol();
Vol v3=new Vol();
v1.setA(3);
v2.setB(3);
v2.setC(4);
v2.setD(5);
v3.setR(3);
v3.setH(5);
System.out.println("边长为"+v1.getA()+"的正方体体积为:"+v1.volume(3));
System.out.println("长、宽、高分别为"+v2.getB()+'、'+v2.getC()+'、'+v2.getD()+"的长方体体积为:"+v2.volume(3,4,5));
System.out.println("半径为"+v3.getR()+','+"高为"+v3.getH()+"的圆柱体体积为:"+v3.volume(3,5));
}

}

public class Vol {

//求边长为l的正方形的体积
public float volume(float l){
return l*l*l;
}

//求长为l,宽为w,高位h的长方形的体积
public float volume(float l,float w,float h){
return l*w*h;
}

//求半径为r,高位h的圆柱形的体积
public float volume(float r,float h){
return (float) (r*r*Math.PI*h);
}
}

public class exp06 {

public static void main(String[] args) {
Vol v=new Vol();
//输出正方形体积
System.out.println(v.volume(3));
//输出长方形体积
System.out.println(v.volume(3,4,5));
//输出圆柱体体积
System.out.println(v.volume(3,5));
//此处是利用了java的多态来求体积,最后输出内容的格式由你自己去修改
}
}

public class Vol {
private double x;
private double y;
private double r;
private double h;

public Vol(double x, double y, double r, double h) {
this.x = x;
this.y = y;
this.r = r;
this.h = h;
}

public Vol() {

}

public double zhengFangTiVol(double x) {
return x * x * x;
}

public double changFangTiVol(double x, double y, double h) {
return x * y * h;
}

public double YuanZhuTiVol(double r, double h) {
return Math.PI * r * r * h;
}

public static void main(String[] args) {
Vol v1 = new Vol();
Vol v2 = new Vol();
Vol v3 = new Vol();
System.out.println(v1.zhengFangTiVol(3));
System.out.println(v2.changFangTiVol(3, 4, 5));
System.out.println(v3.YuanZhuTiVol(3, 5));
}

}

27.0
60.0
141.3716694115407

靠,给的答案你们自己运行过吗。


编程需要学什么?
同时Python且具有丰富和强大的类库,基本上能胜任平时需要的编程工作,而且它对一些新兴的技术例如大数据、机器学习等也有较好的支持 。3、C++:C++语言保留了C语言的有效性、灵活性等特点,又添加了面向对象编程的支持,具有强大的编程功能,可方便地模拟现实问题的过程和操作。它编写出的程序具有结构清晰、...

常见的十五种Java开发工具是什么,有什么特点
绝大多数Java开发工具的文献的问题在于简单地挨个介绍开发工具的每部分组件,但用户在开应用时还需要一个面向任务的手册,利用这个手册你可以不必知道工具每一部分的特定功能就可以开始创建自己的应用。Visual Cafe提供了非常全面的用户指南,它对最开始的安装到创建第一个Java应用和Applet都提供了全面的帮助,...

Java 软件中不能显示菜单
ava编程技巧与最新模块化方式结合到一个单一集成的开发环境中之后才能完成J2EE应用 开发生命周期管理的事实,从根本上得到改变。缺点就是对于初学者来说,较复杂,也 比较难。 6、IBM的Visual Age for Java Visual Age for Java是一个非常成熟的开发工具,它的特性以于IT开发者和业余的 Java编程人员来说都是非常用有...

怎么把java编码设置成全局
ava编程技巧与最新模块化方式结合到一个单一集成的开发环境中之后才能完成J2EE应用 开发生命周期管理的事实,从根本上得到改变。缺点就是对于初学者来说,较复杂,也 比较难。 6、IBM的Visual Age for Java Visual Age for Java是一个非常成熟的开发工具,它的特性以于IT开发者和业余的 Java编程人员来说都是非常用有...

台山市17017427218: java 新手问题 -
凤轻青鹏: 1、属性下的第一个方法或类中的第一个方法不一定定义的就是构造方法 2、类的结构其实是可以自己随便定义的 不过考虑到开发习惯通常是:属性、构造方法、普通方法3、构造方法 在实际的工作之中其实通常是为类中的属性做初始化的(赋值) 4、去掉具体有没有影响 还得看你所定义的某一个类的作用 和 自己的需求5、对于定义类:可以提供多个无参构造方法 但是建议至少保留一个无参构造方法6、对于某些框架的设计其实构造方法的作用是非常大的 因为框架的设计玩的几乎都是反射 而反射就会牵扯都构造方法问题

台山市17017427218: Java初学者必须了解的三大问题是什么呢?
凤轻青鹏: 对于这个系列里的问题,每个学Java的人都应该搞懂.当然,如果只是学Java玩玩就无所谓了.如果你认为自己已经超越初学者了,却不很懂这些问题,请将你自己重归初...

台山市17017427218: 初学JAVA的一个问题. -
凤轻青鹏: 我先必须指明,楼上的回答都是错误的或者不明确的,当你把String换成一个不可拆箱的对象时,就是指向地址,而不是值了,至于JAVA基础数据类型到底是不是真正的值类型,这个问题对于很多java初学者来说都存疑过,我觉得解答的最好的...

台山市17017427218: 初学Java应该注意那些问题?
凤轻青鹏: 其实JAVA是挺简单的一门语言. 相信你也发现了.他入门是很快的. 学习JAVA得注意几点. 一,理解对象的概念.要能把世界万物都看成对象. 二,理解接口.接口是JAVA里面最为灵活的一种对象.有一句形容JAVA语言比较经典的话<面向接口编程> 三,把变化(动作或方法)与那些不容易变化,或者不变化的类,一定分开.这样有足于你去理解可扩展性. 四,多研究多态.. 五,随时保持一种初学者的身份去向他人学习. 其它的废话就不多说了.那都是一些大家都懂的东西.比如:多写多练多看之类的. 自己知道就行了 加油吧. JAVA世界,其实是很美好的.

台山市17017427218: 初学java的几个问题 -
凤轻青鹏: 1、JVM提供了一个Java运行时环境,所有的JVM支持语言在此环境中运行时隔离了不同系统平台的差异性,达到跨平台的目的.2、针对相同函数名的问题,面向对象对两种情况进行了定义,在同一个类中拥有相同函数名的多个方法,则为重载...

台山市17017427218: java入门问题 -
凤轻青鹏: 不管你基础怎么样,不管你学什么语言,就一句话,多动手多上机多看多写代码多做项目 多动手多上机:这个能提高你的动手编程能力,不要只顾着在纸上写写画画的,没用的 多看:一看别人写的代码,来提高自己,明白自己的不足,可以去CSDN上下载,很多资源的;二看java视频教程,介绍几个,张孝祥java就业培训,孙鑫老师的,还有韩顺平的 多写代码多做项目:多写这个不用多说了,多做项目也不一定说必须做那种公司里面写的大项目,你可以写写比如啥记事本啊,日记本啊信息管理系统啥的,按着一定的步骤写着项目流程. 希望以上几点对你有帮助...

台山市17017427218: java新手问题?
凤轻青鹏: java程序实际上是通过JVM来运行的,实际的程序数据都回自动存放在内存的栈里,你每新创建一个对象,新写一个方法和参数,JVM自动给你的数据分配一定大小的栈,然后方法和引用都是通过指针对栈的指向来调用的,这些你学完数据结构后会更清楚.谢谢采纳欢迎追问 编译阶段是由编译器来完成的,java总共包括编译器,虚拟机和各种函数接口来组成

台山市17017427218: java新手小问题
凤轻青鹏: int i=1你已经声明并且赋值也存储在内存中,声明了就开辟了内存空间,不用创建对象了. 首先内存总体分为了4个部分,包括 stack segment 、heap segment、code segment 、data segment ; 其中我们程序中用关键字new出来的东西都是存...

台山市17017427218: 初学JAVA的几个问题
凤轻青鹏: 数据库不属于JAVA的先行课,但JAVA也是有关于数据库部分的操作,这部分就是JDBC里的,初级阶段就不需要涉及到,可以等你学的深入一点再学,你的零基础是指没有学过JAVA吧,那个网上的教程很多啦,我们当时用的教材是JAVA大学教程第六版(英文版),这本挺适合初学者,要真有问题,网上那么多资源都是可以好好利用的,加油吧

台山市17017427218: 新手关于Java的一些问题高手帮忙
凤轻青鹏: 1.println()是输出后在多输出一个“\n”换行符,print()没有,所以println()输出后会重新换行输出第二个println()输出的内容.2.具体情况来看,所有的字符串常量都应该加上双引号.3.输出并换行.4.i*j 的结果转换成字符串输出5.返回上一层目录: cd ..(cd后带两点) 返回根目录:cd \6.子函数运行后返回主函数的数据,子函数可以没有返回值7. 方法名是随便起的,不过需要重载方法,方法名必须与需要重载的方法名称一致

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网