“Java”的版本间的差异

来自tomtalk
跳转至: 导航搜索
Java的辉煌,还能延续多久?
Tom讨论 | 贡献
61条Java面向对象设计的经验原则
第528行: 第528行:
  
 
另外,虽然网络营销培训在国际上LAMP(Linux+Apache+Mysql+Php)架构已经占领了统治地位,但是在中国国内还有一个怪胎,就是基于微软的Windows Server+IIS+SqlServer+ASP/ASP.NET的架构,从理论上说,微软的这一套架构也能实现不错的性能,只可惜Windows和SqlServer价格不菲,整个架构在性能上比起LAMP不仅没有什么优势,反而还有不少劣势,因此微软的这一套家伙在国际市场上吃不开。而国内使用微软盗版则可以忽略成本,而ASP的易学易用性不逊于PHP,甚至连IT外行都能够使用,因此在国内也有不小的市场。但是随着中国在保护知识产权方面的日趋完善,免费的LAMP依旧是未来的趋势。(fblww-0120)
 
另外,虽然网络营销培训在国际上LAMP(Linux+Apache+Mysql+Php)架构已经占领了统治地位,但是在中国国内还有一个怪胎,就是基于微软的Windows Server+IIS+SqlServer+ASP/ASP.NET的架构,从理论上说,微软的这一套架构也能实现不错的性能,只可惜Windows和SqlServer价格不菲,整个架构在性能上比起LAMP不仅没有什么优势,反而还有不少劣势,因此微软的这一套家伙在国际市场上吃不开。而国内使用微软盗版则可以忽略成本,而ASP的易学易用性不逊于PHP,甚至连IT外行都能够使用,因此在国内也有不小的市场。但是随着中国在保护知识产权方面的日趋完善,免费的LAMP依旧是未来的趋势。(fblww-0120)
 
==61条Java面向对象设计的经验原则==
 
 
(1)所有数据都应该隐藏在所在的类的内部。
 
 
(2)类的使用者必须依赖类的共有接口,但类不能依赖它的使用者。
 
 
(3)尽量减少类的协议中的消息。
 
 
(4)实现所有类都理解的最基本公有接口[例如,拷贝操作(深拷贝和浅拷贝)、相等性判断、正确输出内容、从ASCII描述解析等等].
 
 
(5)不要把实现细节(例如放置共用代码的私有函数)放到类的公有接口中。
 
 
如果类的两个方法有一段公共代码,那么就可以创建一个防止这些公共代码的私有函数。
 
 
(6)不要以用户无法使用或不感兴趣的东西扰乱类的公有接口。
 
 
(7)类之间应该零耦合,或者只有导出耦合关系。也即,一个类要么同另一个类毫无关系,要么只使用另一个类的公有接口中的操作。
 
 
(8)类应该只表示一个关键抽象。
 
 
包中的所有类对于同一类性质的变化应该是共同封闭的。一个变化若对一个包影响,则将对包中的所有类产生影响,而对其他的包不造成任何影响 .(9)把相关的数据和行为集中放置。
 
 
设计者应当留意那些通过get之类操作从别的对象中获取数据的对象。这种类型的行为暗示着这条经验原则被违反了。
 
 
(10)把不相关的信息放在另一个类中(也即:互不沟通的行为)。
 
 
朝着稳定的方向进行依赖。
 
 
(11)确保你为之建模的抽象概念是类,而不只是对象扮演的角色。类应当统一地共享工作。
 
 
(13)在你的系统中不要创建全能类/对象。对名字包含Driver、Manager、System、Susystem的类要特别多加小心。
 
 
规划一个接口而不是实现一个接口。
 
 
(14)对公共接口中定义了大量访问方法的类多加小心。大量访问方法意味着相关数据和行为没有集中存放。
 
 
(15)对包含太多互不沟通的行为的类多加小心。
 
 
这个问题的另一表现是在你的应用程序中的类的公有接口中创建了很多的get和set函数。
 
 
(16)在由同用户界面交互的Java面向对象模型构成的应用程序中,模型不应该依赖于界面,界面则应当依赖于模型。
 
 
(17)尽可能地按照现实世界建模(我们常常为了遵守系统功能分布原则、避免全能类原则以及集中放置相关数据和行为的原则而违背这条原则) .(18)从你的设计中去除不需要的类。
 
 
一般来说,我们会把这个类降级成一个属性。
 
 
(19)去除系统外的类。
 
 
系统外的类的特点是,抽象地看它们只往系统领域发送消息但并不接受系统领域内其他类发出的消息。
 
 
(20)不要把操作变成类。质疑任何名字是动词或者派生自动词的类,特别是只有一个有意义行为的类。考虑一下那个有意义的行为是否应当迁移到已经存在或者尚未发现的某个类中。
 
 
(21)我们在创建应用程序的分析模型时常常引入代理类。在设计阶段,我们常会发现很多代理没有用的,应当去除。
 
 
(22)尽量减少类的协作者的数量。
 
 
一个类用到的其他类的数目应当尽量少。
 
 
(23)尽量减少类和协作者之间传递的消息的数量。
 
 
(24)尽量减少类和协作者之间的协作量,也即:减少类和协作者之间传递的不同消息的数量。
 
 
(25)尽量减少类的扇出,也即:减少类定义的消息数和发送的消息数的乘积。
 
 
(26)如果类包含另一个类的对象,那么包含类应当给被包含的对象发送消息。也即:包含关系总是意味着使用关系。
 
 
(27)类中定义的大多数方法都应当在大多数时间里使用大多数数据成员。
 
 
(28)类包含的对象数目不应当超过开发者短期记忆的容量。这个数目常常是6.当类包含多于6个数据成员时,可以把逻辑相关的数据成员划分为一组,然后用一个新的包含类去包含这一组成员。
 
 
(29)让系统功能在窄而深的继承体系中垂直分布。
 
 
(30)在实现语义约束时,最好根据类定义来实现。这常常会导致类泛滥成灾,在这种情况下,约束应当在类的行为中实现,通常是在构造函数中实现,但不是必须如此。
 
 
(31)在类的构造函数中实现语义约束时,把约束测试放在构造函数领域所允许的尽量深的包含层次中。
 
 
(32)Java面向对象中,约束所依赖的语义信息如果经常改变,那么最好放在一个集中式的第3方对象中。
 
 
(33)约束所依赖的语义信息如果很少改变,那么最好分布在约束所涉及的各个类中。
 
 
(34)类必须知道它包含什么,但是不能知道谁包含它。
 
 
(35)共享字面范围(也就是被同一个类所包含)的对象相互之间不应当有使用关系。
 
 
(36)继承只应被用来为特化层次结构建模。
 
 
(37)派生类必须知道基类,基类不应该知道关于它们的派生类的任何信息。
 
 
(38)基类中的所有数据都应当是私有的,不要使用保护数据。
 
 
类的设计者永远都不应该把类的使用者不需要的东西放在公有接口中。
 
 
(39)在理论上,继承层次体系应当深一点,越深越好。
 
 
(40)在实践中,继承层次体系的深度不应当超出一个普通人的短期记忆能力。一个广为接受的深度值是6.(41)所有的抽象类都应当是基类。
 
 
(42)所有的基类都应当是抽象类。
 
 
(43)把数据、行为和/或接口的共性尽可能地放到继承层次体系的高端。
 
 
(44)如果两个或更多个类共享公共数据(但没有公共行为),那么应当把公共数据放在一个类中,每个共享这个数据的类都包含这个类。
 
 
(45)如果两个或更多个类有共同的数据和行为(就是方法),那么这些类的每一个都应当从一个表示了这些数据和方法的公共基类继承。
 
 
(46)如果两个或更多个类共享公共接口(指的是消息,而不是方法),那么只有他们需要被多态地使用时,他们才应当从一个公共基类继承。
 
 
(47)对对象类型的显示的分情况分析一般是错误的。在大多数这样的情况下,设计者应当使用多态。
 
 
(48)对属性值的显示的分情况分析常常是错误的。类应当解耦合成一个继承层次结构,每个属性值都被变换成一个派生类。
 
 
(49)不要通过继承关系来为类的动态语义建模。试图用静态语义关系来为动态语义建模会导致在运行时切换类型。
 
 
(50)不要把类的对象变成派生类。对任何只有一个实例的派生类都要多加小心。
 
 
(51)如果你觉得需要在运行时刻创建新的类,那么退后一步以认清你要创建的是对象。现在,把这些对象概括成一个类。
 
 
(52)在派生类中用空方法(也就是什么也不做的方法)来覆写基类中的方法应当是非法的。
 
 
(53)不要把可选包含同对继承的需要相混淆。把可选包含建模成继承会带来泛滥成灾的类。
 
 
(54)在创建继承层次时,试着创建可复用的框架,而不是可复用的组件。
 
 
(55)如果你在设计中使用了多重继承,先假设你犯了错误。如果没犯错误,你需要设法证明。
 
 
(56)只要在Java面向对象设计中用到了继承,问自己两个问题:(1)派生类是否是它继承的那个东西的一个特殊类型?(2)基类是不是派生类的一部分?
 
 
(57)如果你在一个面向对象设计中发现了多重继承关系,确保没有哪个基类实际上是另一个基类的派生类。
 
 
(58)在面向对象设计中如果你需要在包含关系和关联关系间作出选择,请选择包含关系。
 
 
(59)不要把全局数据或全局函数用于类的对象的薄记工作。应当使用类变量或类方法。
 
 
(60)Java面向对象设计者不应当让物理设计准则来破坏他们的逻辑设计。但是,在对逻辑设计作出决策的过程中我们经常用到物理设计准则。
 
 
(61)不要绕开公共接口去修改对象的状态。
 

2019年12月17日 (二) 03:57的版本



基础入门

hello world

public class HelloWorld{ 
    public static void main(String[] args) {  
        System.out.println("Hello World!"); 
    }
}

java打印数组

将数组转化为有序的List打印出来

import java.util.Arrays; 
 
public class Hello { 
    public static void main(String[] args) {  
        String pool[] = {"dog", "cat", "pig", "main", "fish"};
        System.out.println(Arrays.asList(pool));
    }
}

JAVA中int转String类型有三种方法

int i = 123;
 
String s = String.valueOf(i);
 
String s = Integer.toString(i);
 
String s = i + "";
 
//字符转数字
String str = "123456";
 
i = Integer.parseInt(str);

compareto, equals, == 在java中相对于值和引用

1.compareto是判断一个对象的值是否包含包含另一个对象的值;

例如"abcds".compareto("ab")就是判断abcds中是否含有ab

2.equals 是比较两个对象的值

3.==是比较两个对象内存地址

String A = "abcd";
String B = "abcd"; 
 
A == B;       //ture   
A.equals(B);  //true
 
String A = new String("abcd");
String B = new String("abcd");
A == B;        //false  
A.equals(B);   //true

java中List的初始化问题

我声明了一个

List<String[]> users = null;

然后 使用 add()方法想这个List中加入元素的时候为啥会出现空指针啊。

List当然不能初始化为null,

List<String[]> users = new LinkedList<String[]>();

就可以了,然后添加元素就不会出现空指针了。

Spring

谈谈对ssh三大框架的理解?

SSH框架一般指的是Struts、Spring、Hibernate,后来Struts2代替了Struts。最近5年,Struts2已经被Spring MVC代替,而Hibernate基本也被iBatis/MyBatis代替。

所以你真正需要了解的是Spring,Spring你需要了解两个概念AOP和IOC,更进一步就是Spring的核心技术“动态代理”。

持久层框架看看Hibernate/iBatis/MyBatis,研究一下Spring的数据库事务管理,各个持久层框架式如何实现ORM的,了解至少一种缓存框架,知道什么是数据库连接池。和数据库的交互最核心的不是ORM,而是掌握和数据库相关的能力,比如数据库编程、SQL优化、对范式的理解。

MVC框架Struts2和Spring MVC,你需要知道他们在web.xml文件里配置了一些什么,Struts2/Spring MVC接到前台请求之后经过哪些步骤之后转到Action/Controller,return之后Struts2/Spring MVC又作了些什么。还有就是Filter、Listener和Struts2/Spring MVC的拦截器各有什么特点,适合处理什么样的问题。

Spring Security取username

前台

<%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %>
<security:authentication property="principal.username"></security:authentication>

后台

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = "";
 
if (principal instanceof UserDetails) {
    username = ((UserDetails) principal).getUsername();
} else {
    username = principal.toString();
}
 
System.out.println(username);

favicon.ico引起的spring security登录后跳转错误

在使用spring security登录的时候,用户在某些情况下登录成功的时候莫名被重定向到favicon.ico。

之前一直没发现这个问题是因为在项目中存在favicon.ico文件,这个请求被nginx处理了而未转发给tomcat。

这次因为偷懒还没来得及配置nginx,结果就出现了上面的问题。

出现上述问题的原因是:基本大多数浏览器都会请求favicon.ico这个图标文件用来展示在浏览器的URL地址前面,而这个文件被spring security保护了,所以…有下面的流程:

the user requests URL "/". This URL is cached.

the browser makes a requests to "/favicon.ico". This URL becomes the new URL where to redirect to upon authentication.

the user posts the login form and is redirected to "/favicon.ico"

而解决办法是将favicon.ico加入允许匿名访问.

<http pattern="/favicon.ico" security="none"/>

SPRING MVC 的请求参数获取的几种方法

<form method="post" action="hao.do">
    a: <input id="a" type="text" name="a"/>
    b: <input id="b" type="text" name="b"/>
    <input type="submit" value="Submit" />
</form>

方法1:

public class Pojo{
    private String a;
    private int b;
}
 
@RequestMapping(method = RequestMethod.POST)
public String processSubmit(@ModelAttribute("pojo") Pojo pojo) {
    return "helloWorld";
}

方法2:

@RequestMapping(method = RequestMethod.GET)
public String get(HttpServletRequest request, HttpServletResponse response) {
    System.out.println(request.getParameter("a"));
    return "helloWorld";
}

spring mvc 静态资源 404问题

修改web.xml文件,增加对静态资源的url映射。

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
</servlet-mapping>
 
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.css</url-pattern>
</servlet-mapping>

在web.xml中添加好配置后,在jsp页面就可以引用这些静态资源了。

这里还需要说明的是:这种方法不能访问WEB-INF目录下的静态资源,也就是js目录必须是web根(可能是webapp,webContent等)目录下,否则是不能引用的。

常用代码

随机取读取数据库的一道题

Random random    = new Random(System.currentTimeMillis());
int index_random = random.nextInt(listItem.size());

guid()

private String guid() {
    UUID uuid = UUID.randomUUID();
    String str = uuid.toString();
 
    // 去掉"-"符号
    String temp = str.substring(0, 8) + str.substring(9, 13) + str.substring(14, 18) + str.substring(19, 23) + str.substring(24);
    return temp;
}

Java数字格式化

double pi = 3.1415927;//pi   
 
// 取一位整数   
System.out.println(new DecimalFormat("0").format(pi));// 3   
 
// 取一位整数和两位小数   
System.out.println(new DecimalFormat("0.00").format(pi));// 3.14   
 
// 取两位整数和三位小数,整数不足部分以0填补。   
System.out.println(new DecimalFormat("00.000").format(pi));// 03.142   
 
// 取所有整数部分   
System.out.println(new DecimalFormat("#").format(pi));// 3   
 
// 以百分比方式计数,并取两位小数   
System.out.println(new DecimalFormat("#.##%").format(pi));// 314.16%   
 
long c = 299792458;
 
// 显示为科学计数法,并取五位小数   
System.out.println(new DecimalFormat("#.#####E0").format(c));// 2.99792E8   
 
// 显示为两位整数的科学计数法,并取四位小数   
System.out.println(new DecimalFormat("00.####E0").format(c));// 29.9792E7   
 
// 每三位以逗号进行分隔。   
System.out.println(new DecimalFormat(",###").format(c));// 299,792,458   
 
// 将格式嵌入文本   
System.out.println(new DecimalFormat("光速大小为每秒,###米。").format(c));

生成随机字符

private String RandomString(int length, String type) {
    String number = "0123456789";
    String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    Random random = new Random();
    StringBuffer sb = new StringBuffer();
 
    for (int i = 0; i < length; i++) {
        if (type.equals("number")) {
            int num = random.nextInt(number.length());
            sb.append(number.charAt(num));
        } else {
            int num = random.nextInt(str.length());
            sb.append(str.charAt(num));
        }
    }
 
    return sb.toString();
}

应用

AES加密

java代码

    // 密钥
    private final static String secretKey = "key123";
    private final static String salt = "0123456789abcdef" ;//KeyGenerators.string().generateKey();
 
    /**
     * 加密
     *
     * @param plainString 明文
     * @return
     */
    private static String encrypt(String plainString) {
        // 明文
        byte[] byteArray = plainString.getBytes();
 
        // 加密,设置密钥和随机数
        byte[] cipherArrayTemp = Encryptors.standard(secretKey, salt).encrypt(byteArray);
        byte[] cipherArray = Base64.encode(cipherArrayTemp);
        return new String(cipherArray);
    }
 
    /**
     * 解密
     *
     * @param cipherString 密文
     * @return
     */
    private static String decrypt(String cipherString) {
        // 密文
        byte[] byteArray = cipherString.getBytes();
        byte[] plainArrayTemp = Base64.decode(byteArray);
 
        // 解密
        byte[] plainArray = Encryptors.standard(secretKey, salt).decrypt(plainArrayTemp);
        return new String(plainArray);
    }

javascript代码

https://cdn.bootcss.com/crypto-js/3.1.9-1/crypto-js.js

  // 可在第三方网站解密
  let word = 'hello world!';
  let key = 'key123';
  var iv = '0123456789abcdef';
  var attr = {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  };
  console.log(CryptoJS.AES.encrypt(word, key, attr).toString());
  console.log(CryptoJS.AES.decrypt(CryptoJS.AES.encrypt(word, key), key).toString(CryptoJS.enc.Utf8));

Base64,Base32,Base16进制的区别

刚刚接触Base时,没有太注重区分Base64,Base32,Base16的区别,后面每一次遇到就要去一个一个试,这次花了点时间记下了一下Base的区别,顺便写一下。

在看了大佬们的分析后http://blog.51cto.com/xiaoqin00/1718416,我截取了几个关键的记住这些就能区分Base之间的区别了:

Base64:

包含大写字母(A-Z),小写字母(a-z),数字(0-9)以及+/;

Base32:

而Base32中只有大写字母(A-Z)和数字234567;

Base16:

而Base16就是16进制,他的范围是数字(0-9),字母(ABCDEF);

顺便说一句,当ASCll用Base加密达不到所对应的位数的时候用=号补齐;

在这里附带由三种Base加密的:I love you!

Base64:SSBsb3ZlIHlvde+8gQ==

Base32:JEQGY33WMUQHS33V566IC===

Base16:49206c6f766520796f75efbc81

poi导出excel文件、下载

@RequestMapping(value = "batchCardNoExport", method = RequestMethod.GET)
public void batchCardNoExport(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 创建Excel的工作书册 Workbook,对应到一个excel文档
    HSSFWorkbook wb = new HSSFWorkbook();
 
    // 创建Excel的工作sheet,对应到一个excel文档的tab
    HSSFSheet sheet = wb.createSheet("sheet1");
 
    HSSFRow row;
    HSSFCell cell;
 
    for (int i = 0; i < 60; i++) {
        row = sheet.createRow(i); // 创建Excel的sheet的一行
        for (int j = 0; j < 30; j++) {
            cell = row.createCell(j); // 创建一个Excel的单元格
            cell.setCellValue("hello world " + i + " " + j);
        }
    }
 
    response.setContentType("application/vnd.ms-excel");
    response.setHeader("Content-Disposition", "attachment; filename=filename.xls");
    wb.write(response.getOutputStream()); // Write workbook to response.
    wb.close();
}

如何在mac上安装gradle

首先,先download最新版本的gradle,网址如下:

http://www.gradle.org/get-started

然后将下载下来的zip包放在你要安装的路径上,我安装在

/usr/local/bin;

然后打开电脑上的.bash_profile文件,输入以下命令:

GRADLE_HOME=/usr/local/bin/gradle-1.8;
export GRADLE_HOME
export PATH=$PATH:$GRADLE_HOME/bin

然后再在console上输入以下命令:

source ~/.bash_profile

这样就安装成功啦,可以通过以下命令来查看是否安装成功。

gradle -version

java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

Add mysql.connector-java-x.x.x-bin.jar to your libraries folder. No need to import anything. Have a good one.

别忘了重户tomcat

在IntellIj IDEA中JSP页面 cannot resolve method getParameter("")的解决方案

原来,是我在导入jar包的时候应该选择Platform setting下的global libraries,然后只要导入servlet.jar即可!

一个很诡异的bug,原来是由int精度引起的

import java.util.*; 
import java.text.SimpleDateFormat;
 
public class hello { 
 
 
    public static void main(String[] args) {  
 
        int[] ebbing = {1, 2, 4, 7, 15, 30, 50, 70, 100, 150, 200, 150, 200, 300, 400};
 
        getToday((long)ebbing[0] * 3600 * 24 * 1000); 
        getToday((long)ebbing[1] * 3600 * 24 * 1000); 
        getToday((long)ebbing[2] * 3600 * 24 * 1000); 
        getToday((long)ebbing[3] * 3600 * 24 * 1000); 
        getToday((long)ebbing[4] * 3600 * 24 * 1000); 
        getToday((long)ebbing[5] * 3600 * 24 * 1000); 
        getToday((long)ebbing[6] * 3600 * 24 * 1000); 
        getToday((long)ebbing[7] * 3600 * 24 * 1000); 
        getToday((long)ebbing[8] * 3600 * 24 * 1000); 
    } 
 
    // int为整数类型,在存储的时候,用4个字节存储,范围为-2,147,483,648到2,147,483,647。
    // 原用的是getToday(int offset_ms),这样在第6个日期,就超出范围了。
    public static String getToday(long offset_ms) {
 
    	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); 
		Date date = new Date(System.currentTimeMillis() + offset_ms);
		String today = dateFormat.format(date);
 
        System.out.println(offset_ms + " " + today); 
 
		return today;
    } 
}
# java hello
86400000 2014-05-14
172800000 2014-05-15
345600000 2014-05-17
604800000 2014-05-20
1296000000 2014-05-28
2592000000 2014-06-12
4320000000 2014-07-02
6048000000 2014-07-22
8640000000 2014-08-21

jdk Path设置

只要在Path变量的头部添加如下路径:

C:\Program Files\Java\jdk1.5.0\bin;

就可以了。

java开发环境

  • 安装JDK
  • 设置环境变量
   JAVA_HOME = C:\Program Files\Java\jdk1.8.0_66
   PATH = C:\ProgramData\Oracle\Java\javapath;%JAVA_HOME%\bin;
   CLASSPATH = %JAVA_HOME%\lib; %JAVA_HOME%\lib\dt.jar; %JAVA_HOME%\lib\tools.jar;
  • 安装tomcat
  • 安装IntellJ idea
  • 新建项目,关联tomcat
  • 部署项目:把IntelliJ项目的web目录上传到外网虚拟站点根目录就可以了。
jar xf tomcat.war
chown -R www.www ./*
service tomcat restart

数据库连接不上,把mysql-connector-java-5.1.18-bin.jar放到tomcat/lib目录下,重启。

Java在Web开发语言上败给了PHP

PHP的主要语言开发者之一、Zend公司的创始人之一Andi Gutmans最近在blog中直言不讳地批评了Java语言。他指出,目前Java厂商试图在JVM上提供动态语言实现的路子根本不对,Java已经输掉了Web开发语言的战争,网络营销培训PHP是事实上的标准和胜利者。

Gutmans的这篇文章在技术界引发了强烈争议,很对人对此有不同的意见,我在这里就阐述一下我对PHP和Java两种语言的看法。

我早先曾经在《Perl、PHP、ASP、JSP技术比较》一文中对比过PHP和Java的异同,简而言之,PHP是一种解释执行的脚本语言,语法和C语言类似,易学易用,不懂电脑的非专业人员稍经学习也能使用PHP.而Java要先编译成Class文件,然后在Java虚拟机上执行,Java开发需要熟悉Java语法以及一些核心的架构,从而实现一种可复用的、跨平台的软件,Java比PHP要难学的多。

实际上,从技术架构来说,Java语言相比PHP有明显的优势,Java使用的是面向对象的系统设计方法,而PHP还是采用面向过程的开发方法。PHP只能实现简单的分布式两层或三层的架构,而JAVA可以实现多层架构。数据库层(持久化层)、应用(业务)逻辑层、表示逻辑层彼此分开,而且现在不同的层都已经有一些成熟的开发框架的支持。例如Struts就是利用Java的web开发技术实现了MVC的设计模式,而在业务逻辑层也有Spring框架,数据库持久化层有Hibernate等框架。这些框架可以方便开发者高效、合理、科学得架构多层的商业应用。从数学运算和数据库访问速度来讲,Java的性能也优于PHP.实际上,对于跨平台的大型的企业应用系统来讲,Java几乎已经成为唯一的选择(微软.NET不支持跨平台),但是在于Web网站应用开发来讲,Java却面临着被PHP边缘化的危险,几乎所有的虚拟主机都支持PHP+MySQL,而支持Java的却少之又少,在资源上,网上有不计其数的PHP资源,很多著名的大型网站(例如Facebook、Mediawiki等)都是基于PHP的,而成功的Java网站却寥寥无几,这又是什么原因呢?

Java的理念是“一次编写,到处运行”,Java在应用框架底下的架构是无与伦比的,远胜过其他任何语言,Java的框架利于大型的协同编程开发,系统易维护、可复用性较好。而PHP很容易自学,让热备能快速简洁地编写代码,适合于快速开发,中小型应用系统,开发成本低。在调试、发布上,PHP也较Java简单。

理念上的不同导致了Java和PHP在Web应用开发上显示了不同的结果,尽管Java的数学计算和数据库访问都有优势,架构也相当完美,但是PHP却可以简单轻松地支持高强度Web访问,能够快速开发应用,支持PHP的虚拟主机多如牛毛,使得用PHP开发一个网站比用Java开发一个网站要快得多,容易的多。Java所拥有的优点只适合传统的以软件项目为核心的开发模式,而PHP更适合于以客户为核心的SaaS的开发模式,因此,PHP目前在Web网站开发的优势完全是因为Web网站开发的特殊性而导致的,并非编程语言特性所决定。

因此,PHP在Web网站开发语言的战争中已经慢慢将Java抛在了后面,Java要想在Web网站开发上奋起直追,的确应该多听听Andi Gutmans的意见,彻底改变一下思路才行,否则两者的差距只能是越来越远。

另外,虽然网络营销培训在国际上LAMP(Linux+Apache+Mysql+Php)架构已经占领了统治地位,但是在中国国内还有一个怪胎,就是基于微软的Windows Server+IIS+SqlServer+ASP/ASP.NET的架构,从理论上说,微软的这一套架构也能实现不错的性能,只可惜Windows和SqlServer价格不菲,整个架构在性能上比起LAMP不仅没有什么优势,反而还有不少劣势,因此微软的这一套家伙在国际市场上吃不开。而国内使用微软盗版则可以忽略成本,而ASP的易学易用性不逊于PHP,甚至连IT外行都能够使用,因此在国内也有不小的市场。但是随着中国在保护知识产权方面的日趋完善,免费的LAMP依旧是未来的趋势。(fblww-0120)