JAVA CDI 学习(1) - @Inject基本用法

CDI(Contexts and Dependency Injection 上下文依赖注入),是JAVA官方提供的依赖注入实现,可用于Dynamic Web Module中,先给3篇老外的文章,写得很不错

1、Java EE CDI Dependency Injection (@Inject) tutorial
2、Java EE CDI Producer methods tutorial
3、Java EE CDI bean scopes

此外,还有jboss官方的参考文档:http://docs.jboss.org/weld/reference/latest/en-US/html/

如果不想啃洋文,也可以继续往下看:

一、基本的Inject注入

1.1 在eclipse中先创建一个常规的maven Dynamic Web项目(不熟悉maven的,可以先看看这里),下面是完整的项目截图

里面各package的代码,后面会给出。 项目的属性中,注意有几个属性要勾上(默认情况下,应该已经自动勾上了),如下图:

上图右侧的圆圈,其实就是CDI 1.0使用的先决条件。

Pom.xml的内容如下:

  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <!--
  3     JBoss, Home of Professional Open Source
  4     Copyright 2013, Red Hat, Inc. and/or its affiliates, and individual
  5     contributors by the @authors tag. See the copyright.txt in the
  6     distribution for a full listing of individual contributors.
  7
  8     Licensed under the Apache License, Version 2.0 (the "License");
  9     you may not use this file except in compliance with the License.
 10     You may obtain a copy of the License at
 11     http://www.apache.org/licenses/LICENSE-2.0
 12     Unless required by applicable law or agreed to in writing, software
 13     distributed under the License is distributed on an "AS IS" BASIS,
 14     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15     See the License for the specific language governing permissions and
 16     limitations under the License.
 17 -->
 18 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 19     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 20     <modelVersion>4.0.0</modelVersion>
 21
 22     <groupId>cnblogs</groupId>
 23     <artifactId>cdi-web-sample</artifactId>
 24     <version>0.0.1-SNAPSHOT</version>
 25     <packaging>war</packaging>
 26     <name>cdi-web-sample</name>
 27     <description>A starter Java EE 6 webapp project for use on JBoss AS 7 / EAP 6, generated from the jboss-javaee6-webapp archetype</description>
 28
 29     <url>http://jboss.org/jbossas</url>
 30     <licenses>
 31         <license>
 32             <name>Apache License, Version 2.0</name>
 33             <distribution>repo</distribution>
 34             <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
 35         </license>
 36     </licenses>
 37
 38     <properties>
 39         <!-- Explicitly declaring the source encoding eliminates the following
 40             message: -->
 41         <!-- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered
 42             resources, i.e. build is platform dependent! -->
 43         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 44
 45         <!-- JBoss dependency versions -->
 46         <version.jboss.maven.plugin>7.4.Final</version.jboss.maven.plugin>
 47
 48         <!-- Define the version of the JBoss BOMs we want to import to specify
 49             tested stacks. -->
 50         <version.jboss.bom>1.0.7.Final</version.jboss.bom>
 51         <!-- Alternatively, comment out the above line, and un-comment the line
 52             below to use version 1.0.4.Final-redhat-4 which is a release certified to
 53             work with JBoss EAP 6. It requires you have access to the JBoss EAP 6
 54             maven repository. -->
 55         <!-- <version.jboss.bom>1.0.4.Final-redhat-4</version.jboss.bom>> -->
 56
 57         <!-- other plugin versions -->
 58         <version.surefire.plugin>2.10</version.surefire.plugin>
 59         <version.war.plugin>2.1.1</version.war.plugin>
 60
 61         <!-- maven-compiler-plugin -->
 62         <maven.compiler.target>1.6</maven.compiler.target>
 63         <maven.compiler.source>1.6</maven.compiler.source>
 64     </properties>
 65
 66
 67     <dependencyManagement>
 68         <dependencies>
 69             <!-- JBoss distributes a complete set of Java EE 6 APIs including a Bill
 70                 of Materials (BOM). A BOM specifies the versions of a "stack" (or a collection)
 71                 of artifacts. We use this here so that we always get the correct versions
 72                 of artifacts. Here we use the jboss-javaee-6.0-with-tools stack (you can
 73                 read this as the JBoss stack of the Java EE 6 APIs, with some extras tools
 74                 for your project, such as Arquillian for testing) and the jboss-javaee-6.0-with-hibernate
 75                 stack you can read this as the JBoss stack of the Java EE 6 APIs, with extras
 76                 from the Hibernate family of projects) -->
 77             <dependency>
 78                 <groupId>org.jboss.bom</groupId>
 79                 <artifactId>jboss-javaee-6.0-with-tools</artifactId>
 80                 <version>${version.jboss.bom}</version>
 81                 <type>pom</type>
 82                 <scope>import</scope>
 83             </dependency>
 84             <dependency>
 85                 <groupId>org.jboss.bom</groupId>
 86                 <artifactId>jboss-javaee-6.0-with-hibernate</artifactId>
 87                 <version>${version.jboss.bom}</version>
 88                 <type>pom</type>
 89                 <scope>import</scope>
 90             </dependency>
 91         </dependencies>
 92     </dependencyManagement>
 93
 94     <dependencies>
 95
 96         <!-- First declare the APIs we depend on and need for compilation. All
 97             of them are provided by JBoss AS 7 -->
 98
 99         <!-- Import the CDI API, we use provided scope as the API is included in
100             JBoss AS 7 -->
101         <dependency>
102             <groupId>javax.enterprise</groupId>
103             <artifactId>cdi-api</artifactId>
104             <scope>provided</scope>
105         </dependency>
106
107         <!-- Import the Common Annotations API (JSR-250), we use provided scope
108             as the API is included in JBoss AS 7 -->
109         <dependency>
110             <groupId>org.jboss.spec.javax.annotation</groupId>
111             <artifactId>jboss-annotations-api_1.1_spec</artifactId>
112             <scope>provided</scope>
113         </dependency>
114
115         <!-- Import the JAX-RS API, we use provided scope as the API is included
116             in JBoss AS 7 -->
117         <dependency>
118             <groupId>org.jboss.spec.javax.ws.rs</groupId>
119             <artifactId>jboss-jaxrs-api_1.1_spec</artifactId>
120             <scope>provided</scope>
121         </dependency>
122
123         <!-- Import the JPA API, we use provided scope as the API is included in
124             JBoss AS 7 -->
125         <dependency>
126             <groupId>org.hibernate.javax.persistence</groupId>
127             <artifactId>hibernate-jpa-2.0-api</artifactId>
128             <scope>provided</scope>
129         </dependency>
130
131         <!-- Import the EJB API, we use provided scope as the API is included in
132             JBoss AS 7 -->
133         <dependency>
134             <groupId>org.jboss.spec.javax.ejb</groupId>
135             <artifactId>jboss-ejb-api_3.1_spec</artifactId>
136             <scope>provided</scope>
137         </dependency>
138
139         <!-- JSR-303 (Bean Validation) Implementation -->
140         <!-- Provides portable constraints such as @Email -->
141         <!-- Hibernate Validator is shipped in JBoss AS 7 -->
142         <dependency>
143             <groupId>org.hibernate</groupId>
144             <artifactId>hibernate-validator</artifactId>
145             <scope>provided</scope>
146             <exclusions>
147                 <exclusion>
148                     <groupId>org.slf4j</groupId>
149                     <artifactId>slf4j-api</artifactId>
150                 </exclusion>
151             </exclusions>
152         </dependency>
153
154         <!-- Import the JSF API, we use provided scope as the API is included in
155             JBoss AS 7 -->
156         <dependency>
157             <groupId>org.jboss.spec.javax.faces</groupId>
158             <artifactId>jboss-jsf-api_2.1_spec</artifactId>
159             <scope>provided</scope>
160         </dependency>
161
162         <!-- Now we declare any tools needed -->
163
164         <!-- Annotation processor to generate the JPA 2.0 metamodel classes for
165             typesafe criteria queries -->
166         <dependency>
167             <groupId>org.hibernate</groupId>
168             <artifactId>hibernate-jpamodelgen</artifactId>
169             <scope>provided</scope>
170         </dependency>
171
172         <!-- Annotation processor that raising compilation errors whenever constraint
173             annotations are incorrectly used. -->
174         <dependency>
175             <groupId>org.hibernate</groupId>
176             <artifactId>hibernate-validator-annotation-processor</artifactId>
177             <scope>provided</scope>
178         </dependency>
179
180         <!-- Needed for running tests (you may also use TestNG) -->
181         <dependency>
182             <groupId>junit</groupId>
183             <artifactId>junit</artifactId>
184             <scope>test</scope>
185         </dependency>
186
187         <!-- Optional, but highly recommended -->
188         <!-- Arquillian allows you to test enterprise code such as EJBs and Transactional(JTA)
189             JPA from JUnit/TestNG -->
190         <dependency>
191             <groupId>org.jboss.arquillian.junit</groupId>
192             <artifactId>arquillian-junit-container</artifactId>
193             <scope>test</scope>
194         </dependency>
195
196         <dependency>
197             <groupId>org.jboss.arquillian.protocol</groupId>
198             <artifactId>arquillian-protocol-servlet</artifactId>
199             <scope>test</scope>
200         </dependency>
201
202     </dependencies>
203
204     <build>
205         <!-- Maven will append the version to the finalName (which is the name
206             given to the generated war, and hence the context root) -->
207         <finalName>${project.artifactId}</finalName>
208         <plugins>
209             <plugin>
210                 <artifactId>maven-war-plugin</artifactId>
211                 <version>${version.war.plugin}</version>
212                 <configuration>
213                     <!-- Java EE 6 doesn't require web.xml, Maven needs to catch up! -->
214                     <failOnMissingWebXml>false</failOnMissingWebXml>
215                 </configuration>
216             </plugin>
217             <!-- The JBoss AS plugin deploys your war to a local JBoss AS container -->
218             <!-- To use, run: mvn package jboss-as:deploy -->
219             <plugin>
220                 <groupId>org.jboss.as.plugins</groupId>
221                 <artifactId>jboss-as-maven-plugin</artifactId>
222                 <version>${version.jboss.maven.plugin}</version>
223             </plugin>
224         </plugins>
225     </build>
226
227     <profiles>
228         <profile>
229             <!-- The default profile skips all tests, though you can tune it to run
230                 just unit tests based on a custom pattern -->
231             <!-- Seperate profiles are provided for running all tests, including Arquillian
232                 tests that execute in the specified container -->
233             <id>default</id>
234             <activation>
235                 <activeByDefault>true</activeByDefault>
236             </activation>
237             <build>
238                 <plugins>
239                     <plugin>
240                         <artifactId>maven-surefire-plugin</artifactId>
241                         <version>${version.surefire.plugin}</version>
242                         <configuration>
243                             <skip>true</skip>
244                         </configuration>
245                     </plugin>
246                 </plugins>
247             </build>
248         </profile>
249
250         <profile>
251             <!-- An optional Arquillian testing profile that executes tests in your
252                 JBoss AS instance -->
253             <!-- This profile will start a new JBoss AS instance, and execute the
254                 test, shutting it down when done -->
255             <!-- Run with: mvn clean test -Parq-jbossas-managed -->
256             <id>arq-jbossas-managed</id>
257             <dependencies>
258                 <dependency>
259                     <groupId>org.jboss.as</groupId>
260                     <artifactId>jboss-as-arquillian-container-managed</artifactId>
261                     <scope>test</scope>
262                 </dependency>
263             </dependencies>
264         </profile>
265
266         <profile>
267             <!-- An optional Arquillian testing profile that executes tests in a remote
268                 JBoss AS instance -->
269             <!-- Run with: mvn clean test -Parq-jbossas-remote -->
270             <id>arq-jbossas-remote</id>
271             <dependencies>
272                 <dependency>
273                     <groupId>org.jboss.as</groupId>
274                     <artifactId>jboss-as-arquillian-container-remote</artifactId>
275                     <scope>test</scope>
276                 </dependency>
277             </dependencies>
278         </profile>
279
280         <profile>
281             <!-- When built in OpenShift the 'openshift' profile will be used when
282                 invoking mvn. -->
283             <!-- Use this profile for any OpenShift specific customization your app
284                 will need. -->
285             <!-- By default that is to put the resulting archive into the 'deployments'
286                 folder. -->
287             <!-- http://maven.apache.org/guides/mini/guide-building-for-different-environments.html -->
288             <id>openshift</id>
289             <build>
290                 <plugins>
291                     <plugin>
292                         <artifactId>maven-war-plugin</artifactId>
293                         <version>${version.war.plugin}</version>
294                         <configuration>
295                             <outputDirectory>deployments</outputDirectory>
296                             <warName>ROOT</warName>
297                         </configuration>
298                     </plugin>
299                 </plugins>
300             </build>
301         </profile>
302
303     </profiles>
304 </project>

pom.xml

 

1.2 model包下,会创建Product类

 1 package model;
 2
 3 public class Product {
 4
 5     private String productName;
 6
 7     private String productNo;
 8
 9     public String getProductNo() {
10         return productNo;
11     }
12
13     public void setProductNo(String productNo) {
14         this.productNo = productNo;
15     }
16
17     public String getProductName() {
18         return productName;
19     }
20
21     public void setProductName(String productName) {
22         this.productName = productName;
23     }
24
25     public String toString() {
26         return this.productName + " "    + this.productNo;
27
28     }
29 }

Product

这个类其实是打酱油的

 

1.3 service包下,建一个ProductService接口

1 package service;
2
3 import model.Product;
4
5 public interface ProductService {
6
7     Product getNewProduct();
8
9 }

ProductService

 

1.4 service包下,再来几个实现

 1 package service;
 2
 3 import javax.inject.Inject;
 4
 5 import model.Product;
 6
 7 public abstract class BaseProductServiceImpl implements ProductService {
 8
 9     @Inject
10     protected Product product;
11
12
13     public abstract Product getNewProduct();
14 }

BaseProductServiceImpl

这个是实现类的基类,注意这里私有成员上打了一个注解@Inject,表示运行时将动态注入(实例化)一个Product

再来二个具体的实现类,BookProductServiceImpl生成"书籍"

 1 package service;
 2
 3 import annotation.Book;
 4 import model.Product;
 5
 6 @Book
 7 public class BookProductServiceImpl extends BaseProductServiceImpl {
 8
 9     public Product getNewProduct() {
10         product.setProductName("论程序员的自我修养");
11         product.setProductNo("ISBN 999");
12         return product;
13     }
14
15 }

BookProductServiceImpl

TelephoneProductServiceImpl生成“电话”

 1 package service;
 2
 3 import annotation.Telephone;
 4 import model.Product;
 5
 6 @Telephone
 7 public class TeletephoneProductServiceImpl extends BaseProductServiceImpl {
 8
 9     public Product getNewProduct() {
10         product.setProductName("NOKIA LUMIA");
11         product.setProductNo("920");
12         return product;
13     }
14
15 }

TeletephoneProductServiceImpl

可能有朋友注意到了,里面用到了二个自己写的注释@Book和@Telephone,接下来会讲到,这里先忽略

 

1.5 controller包下,添加IndexController类

为了能跟JSF的前台页面交互,这里需要添加一个Controller

 1 package controller;
 2
 3 import javax.faces.bean.ManagedBean;
 4 import javax.inject.Inject;
 5
 6 import annotation.*;
 7 import service.*;
 8
 9 @ManagedBean(name = "Index")
10 public class IndexController {
11
12     @Inject
13     @Book
14     private ProductService bookProductService;
15
16     @Inject
17     @Telephone
18     private ProductService telephoneProductService;
19
20     public ProductService getBookProductService() {
21         return bookProductService;
22     }
23
24     public ProductService getTelephoneProductService() {
25         return telephoneProductService;
26     }
27
28 }
29 IndexController

IndexController

好了,一下子搞了这么多代码,先停下来消化一下,这里我们模拟了分层架构:

model - 代表了业务模型层(本例中,为了简单起见,没有细分 业务模型、实体模型、以及web中的ViewModel)

service - 代表了服务层(为了简单起见,我们把接口+实现都放在一起了,实际中,可能会把这二个分开来)

controller - 这是web层MVC中的控制器层

当然,为了能展示最终的效果,我们会在后面加一个页面做为View层来提供UI

 

1.6 webapp下,新建一个index.xhtml文件,内容如下:

 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 2 <html xmlns="http://www.w3.org/1999/xhtml"
 3     xmlns:h="http://java.sun.com/jsf/html"
 4     xmlns:f="http://java.sun.com/jsf/core"
 5     xmlns:ui="http://java.sun.com/jsf/facelets">
 6
 7 <h:head></h:head>
 8 <body>
 9     Book:
10     <br /> #{Index.bookProductService.newProduct.toString()}
11     <br />
12     <br /> Telephone:
13     <br /> #{Index.telephoneProductService.newProduct.toString()}
14 </body>

index.xhtml

页面里几乎没啥代码,就是调用IndexController实例中的getBookProductService、getTelephoneProductService方法,进而得到相应的"服务实现类实例",最终输出产品信息

 

1.7 Inject用在什么地方了?

a) 页面显示时,IndexController里,bookProductService和telephoneProductService这二个私有成员上,都加了@Inject注解,所以运行时,这二个成员都能被实例化,但是问题来了,它们都是ProductService的接口类型,而这个接口有二个具体的实现(BookProductServiceImpl和TeletephoneProductServiceImpl),最终运行时,应该实现化哪一个呢?

关键在于另一个注解@Book和@Telephone,观察一下:BookProductServiceImpl类上我们也加了@Book,而TeletephoneProductServiceImpl上加了@Telephone,这样正好可以跟IndexControll中这二个私成成员的注释“匹配”上,所以最终系统知道私有成员bookProductService应该被实例化成BookProductServiceImpl,telephoneProductService被实例化成TeletephoneProductServiceImpl

@Book和@Telephone的代码如下:

 1 package annotation;
 2
 3 import java.lang.annotation.Retention;
 4 import java.lang.annotation.RetentionPolicy;
 5
 6 import javax.inject.Qualifier;
 7
 8 @Qualifier
 9 @Retention(RetentionPolicy.RUNTIME)
10 public @interface Book {
11
12 }

Book

 1 package annotation;
 2
 3 import java.lang.annotation.Retention;
 4 import java.lang.annotation.RetentionPolicy;
 5 import javax.inject.Qualifier;
 6
 7 @Qualifier
 8 @Retention(RetentionPolicy.RUNTIME)
 9 public @interface Telephone {
10
11 }

Telephone

b) BaseProductServiceImpl中,在私成成员product上加了@Inject,这样运行时,能自动实例化Product对象

 

1.8 运行结果

jboss中部署后,浏览http://localhost:8080/cdi-web-sample/faces/index.xhtml 或http://localhost:8080/cdi-web-sample/index.jsf

 

1.9 Method(方法)注入及Constructor(构造器)注入

刚才我们看到的都是在Field(成员)上注入,除了这种方式,也可以在Method或Constructor上注入

 1     private Product product ;
 2
 3     /**
 4      * 演示在方法上使用@Inject注入
 5      * @param p
 6      */
 7     @Inject
 8     public void setProduct(Product p){
 9         product = p;
10     }
11
12     public Product getProduct(){
13         return product;
14     }

Method Inject

上面的代码即是Method注入的示例,最后来看下构造器注入,我们再新建一个ClothProductServiceImpl用于生产服装

 1 package service;
 2
 3 import javax.inject.Inject;
 4
 5 import annotation.*;
 6 import model.Product;
 7
 8 @Cloth
 9 public class ClothProductServiceImpl implements ProductService {
10
11     private Product product;
12
13     /**
14      * 构造器注入
15      * @param p
16      */
17     @Inject
18     public ClothProductServiceImpl(Product p ){
19         p.setProductName("A New Dress");
20         p.setProductNo("SPRIT-001");
21         product = p;
22
23     }
24
25     public Product getNewProduct() {
26         return product;
27     }
28
29 }

Constructor Inject

运行时,系统会自动给构造器ClothProductServiceImpl传递一个实例化的Product对象作为参数,以实现Product实例的注入

附文中示例源码下载:cdi-web-sample.zip

下一节,我们将学习Bean注入后的生命周期管理

时间: 2024-11-04 00:55:07

JAVA CDI 学习(1) - @Inject基本用法的相关文章

JAVA CDI 学习(4) - @Alternative/@Default/@Any &amp; Extension

前面几节学习到的CDI内容,基本上都是hard-code,以硬编码的方式在代码里指定注入类型,这并非依赖注入的本意,依赖注入的优势之一在于"解耦",这一节我们将学习如何利用配置来动态注入的类型及属性初始化. 一.@Alternative/@Default/@Any 当一个服务接口(也称契约)有多个实现时,可以在代码里指定一个缺省的实现类型(即:标注成@Default或@Any),其它实现类标注成@Alternative,以后如果需要动态切换实现类,只要在webapp/WEB-INF/b

JAVA CDI 学习(2) - Scope 生命周期

在上一节中,我们已经知道了如何用@Inject实现基本注入,这一节研究Bean实例注入后的"生命周期",web application中有几种基本的生命周期(不管哪种编程语言都类似) 1.Application 生命周期 即:web application启动后,处于该生命周期级别的对象/变量,将一直存在,可以被所有web应用的用户共同访问,通常用来做网站计数器,实现流量访问之类.直到web 应用停止或重新启动,该对象才被销毁.简单来说:只要web application处于激活状态,

JAVA CDI 学习(5) - 如何向RESTFul Service中注入EJB实例

RESTFul Service中如果要注入EJB实例,常规的@Inject将不起作用,在Jboss中,应用甚至都启动不起来(因为@Inject注入失败),解决方法很简单:将@Inject换成@EJB 参考代码: CityInvoker是一个Stateless的EJB package test; import javax.ejb.Stateless; import ... @Stateless public class CityInvoker { public CityResponse getCi

【Java面向对象学习】一张图搞定Java面向对象

刚开始学习Java的时候,一个人跌跌撞撞摸索着往前走,很多东西理解的也懵懵懂懂,后来实践的多了,才慢慢清楚:许多东西虽然很基础但是却很重要,是需要反复思考和加深理解的,[Java面向对象学习]一张图搞定Java面向对象,分享一些归纳总结后的技术干货,一张图能搞定的事,绝对不长篇大论. 大家都知道,Java面向对象是Java的一个核心,也是初学者的一个难点,所以我们从这里开始,Let's go ! Java面向对象 面向对象(Oriented Object) 是相对于面向过程而言的,过程其实就是函

java interface的两个经典用法_java

本文为大家分享了java interface的两个经典用法,供大家参考,具体内容如下 1.Java多态接口动态加载实例 编写一个通用程序,用来计算没一种交通工具运行1000公里所需的时间,已知每种交通工具的参数都为3个整数A.B.C的表达式.现有两种工具:Car和Plane,其中Car的速度运算公式为:A+B+C.需要编写三个类:ComputeTime.java,Palne.java,Car.java和接口Common.java.要求在未来如果增加第3中交通工具的时候,不必修改 以前的任何程序,

Java中BigDecimal类的简单用法_java

本文实例讲述了Java中BigDecimal类的简单用法,是Java程序设计中非常实用的技巧,分享给大家供大家参考.具体用法分析如下: 一般来说,一提到Java里面的商业计算,我们都知道不能用float和double,因为他们无法进行精确计算.但是Java的设计者给编程人员提供了一个很有用的类BigDecimal,他可以完善float和double类无法进行精确计算的缺憾.BigDecimal类位于java.maths类包下.首先我们来看下如何构造一个BigDecimal对象.它的构造函数很多,

Android编程学习之抽象类AbsListView用法实例分析_Android

本文实例讲述了Android编程学习之抽象类AbsListView用法.分享给大家供大家参考,具体如下: 一.继承关系 public abstract class AbsListView extends AdapterView <T extendsAdapter> java.lang.Object          android.view.View                android.view.ViewGroup                       android.widg

Android编程学习之抽象类AbsListView用法实例分析

本文实例讲述了Android编程学习之抽象类AbsListView用法.分享给大家供大家参考,具体如下: 一.继承关系 public abstract class AbsListView extends AdapterView <T extendsAdapter> java.lang.Object          android.view.View                android.view.ViewGroup                       android.widg

Java语言学习的要点

    Java的学习是比较复杂的,主要表现在相关的一系列平台.规范和协议上.有经验的Java程序员都知道,只掌握了Java语言本身很难开发应用程序.本文不讨论这些复杂的概念,而是从初学者的角度,对于Java语言本身的学习提出自己的见解和建议.本文的讨论基于以下假设:? 学习的目的是为了将来进行应用程序的开发,而不是进行语言理论研究? 将来的应用开发是在成熟的平台上展开,而不是自己从底层开发平台掌握静态方法和属性静态方法和属性用于描述某一类对象群体的特征,而不是单个对象的特征.java中大量应用